[CC-COUPLES]Couples sit next to each other
题目大意:
有(n(nle5 imes10^5))对小伙伴共(2n)个人坐成一圈。刚开始编号为(i)的人坐在第(i)个座位上。每次可以让相邻的两个人交换座位。问要让每一对小伙伴的座位都相邻至少需要多少次交换?
思路:
答案为每一对两个人距离之和-“交叉”的小伙伴的对数。树状数组维护即可。
时间复杂度(mathcal O(nlog n))。
源代码:
#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
typedef long long int64;
const int N=5e5+1;
int n,a[N*2],pos[N][2],cnt[N];
class FenwickTree {
private:
int val[N*2];
int lowbit(const int &x) const {
return x&-x;
}
public:
void modify(int p,const int &x) {
for(;p<=n*2;p+=lowbit(p)) {
val[p]+=x;
}
}
int query(int p) const {
int ret=0;
for(;p;p-=lowbit(p)) {
ret+=val[p];
}
return ret;
}
int query(const int &l,const int &r) const {
return query(r)-query(l-1);
}
};
FenwickTree t;
int main() {
for(register int T=getint();T;T--) {
n=getint();
std::fill(&cnt[1],&cnt[n]+1,0);
for(register int i=1;i<=n*2;i++) {
const int &x=a[i]=getint();
pos[x][cnt[x]++]=i;
}
int64 ans=0;
for(register int i=1;i<=n;i++) {
ans+=std::min(pos[i][1]-pos[i][0],n*2+pos[i][0]-pos[i][1])-1;
}
for(register int i=1;i<=n*2;i++) {
const int &x=a[i];
if(i==pos[x][0]) {
t.modify(i,1);
}
if(i==pos[x][1]) {
t.modify(pos[x][0],-1);
ans-=t.query(pos[x][0],i);
}
}
printf("%lld
",ans);
}
return 0;
}