题解:交换某节点的两棵子树仅对 此节点子树对答案的贡献 有影响
Dfs,启发式合并时顺便求逆序对即可,贪心交不交换
O(nlogn*logn)
Noname讲过一种合并Treap求逆序对,仅需O(nlogn),还不会
注意:插入时维护路径上的siz,插入完Splay到根节点的儿子
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn=300009;
int n;
long long ans;
int nn;
int fa[maxn],ch[maxn][2],siz[maxn],ky[maxn];
inline int son(int x){
if(ch[fa[x]][0]==x)return 0;
else return 1;
}
void pushup(int x){
siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}
inline void Rotate(int x){
int y=fa[x];
int z=fa[y];
int b=son(x),c=son(y);
int a=ch[x][b^1];
if(z)ch[z][c]=x;
fa[x]=z;
if(a)fa[a]=y;
ch[y][b]=a;
fa[y]=x;ch[x][b^1]=y;
pushup(y);pushup(x);
}
void Splay(int x,int i){
while(fa[x]!=i){
int y=fa[x];
int z=fa[y];
if(z==i){
Rotate(x);
}else{
if(son(x)==son(y)){
Rotate(y);Rotate(x);
}else{
Rotate(x);Rotate(x);
}
}
}
}
int Ins(int p,int root){
int ret=0;
int x=root,y=0;
while(x){
siz[x]++;
y=x;
if(ky[p]>ky[x]){
ret+=siz[ch[x][0]]+1;
x=ch[x][1];
}else{
x=ch[x][0];
}
}
x=p;
fa[x]=y;ch[x][0]=ch[x][1]=0;siz[x]=1;
if(y){
if(ky[x]>ky[y])ch[y][1]=x;
else ch[y][0]=x;
}
Splay(x,root);
return ret;
}
long long Mer(int x,int root){
long long ret=0;
int rs=ch[x][1];
if(ch[x][0])ret+=Mer(ch[x][0],root);
ret+=Ins(x,root);
if(rs)ret+=Mer(rs,root);
return ret;
}
//int Getsmall(int val,int root){
// int ret=0,x=root;
// while(x){
// if(val>ky[x]){
// ret+=siz[ch[x][0]]+1;
// x=ch[x][1];
// }else{
// x=ch[x][0];
// }
// }
// return ret;
//}
//long long Tong(int x,int root){
// long long ret=0;
// ret=Getsmall(ky[x],root);
// if(ch[x][0])ret+=Tong(ch[x][0],root);
// if(ch[x][1])ret+=Tong(ch[x][1],root);
// return ret;
//}
int Dfs(){
int r;
scanf("%d",&r);
if(r){
++nn;
fa[nn]=ch[nn][0]=ch[nn][1]=0;
ky[nn]=r;siz[nn]=1;
return nn;
}else{
int x=Dfs();
int y=Dfs();
long long tm=0,tm2=0;
long long sizx=siz[x];
long long sizy=siz[y];
if(siz[x]<siz[y]){
tm=Mer(x,y)-sizx*(sizx-1)/2;
tm2=sizx*sizy-tm;
ans+=min(tm,tm2);
}else{
tm=sizx*sizy-(Mer(y,x)-sizy*(sizy-1)/2);
tm2=sizx*sizy-tm;
ans+=min(tm,tm2);
}
Splay(x,0);
return x;
}
}
int main(){
scanf("%d",&n);
Dfs();
printf("%lld
",ans);
return 0;
}