BZOJ 2212 [Poi2011]Tree Rotations
题解:交换某节点的两棵子树仅对 此节点子树对答案的贡献 有影响
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\n",ans); return 0; }
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!