BZOJ 2212 [Poi2011]Tree Rotations

xiaoxiao2021-02-28  47

题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=2212

思路

显然,一棵子树内的交换情况,并不会影响 这个子树与其他子树之间 的逆序对个数。

对每个点建一棵权值线段树,用线段树统计逆序对,然后搜索,搜到一个点,就把他的左右儿子代表的线段树合并,并计算左右儿子逆序对个数。

代码

#include <cstdio> #include <algorithm> const int maxn=400000; const int maxd=4000000; int read() { int x=0,f=1; char ch=getchar(); while((ch<'0')||(ch>'9')) { if(ch=='-') { f=-f; } ch=getchar(); } while((ch>='0')&&(ch<='9')) { x=x*10+ch-'0'; ch=getchar(); } return x*f; } struct node { node* son[2]; int sum; }; node* root[maxn+10]; node tnode[maxd+10]; int ls[maxn+10],rs[maxn+10],tot,n,cnt,val[maxn+10],num,fa[maxn+10]; long long ans,na,nb; inline int updata(node* now) { now->sum=0; if(now->son[0]!=NULL) { now->sum+=now->son[0]->sum; } if(now->son[1]!=NULL) { now->sum+=now->son[1]->sum; } return 0; } node* build(node* now,int l,int r,int v) { if(l==r) { now->son[0]=now->son[1]=NULL; now->sum=1; return 0; } int mid=(l+r)>>1; if(v<=mid) { build(now->son[0]=&tnode[++cnt],l,mid,v); now->son[1]=NULL; } else { now->son[0]=NULL; build(now->son[1]=&tnode[++cnt],mid+1,r,v); } updata(now); return 0; } node* merge(node* a,node* b,int l,int r) { if(a==NULL) { return b; } if(b==NULL) { return a; } int mid=(l+r)>>1; if((a->son[1]!=NULL)&&(b->son[0]!=NULL)) { na+=1ll*a->son[1]->sum*b->son[0]->sum; } if((a->son[0]!=NULL)&&(b->son[1]!=NULL)) { nb+=1ll*a->son[0]->sum*b->son[1]->sum; } a->son[0]=merge(a->son[0],b->son[0],l,mid); a->son[1]=merge(a->son[1],b->son[1],mid+1,r); updata(a); return a; } inline int ins(int a,int b) { if(ls[a]!=0) { rs[a]=b; } else { ls[a]=b; } fa[b]=a; return 0; } int search(int u) { if(ls[u]!=0) { search(ls[u]); search(rs[u]); na=nb=0; root[u]=merge(root[ls[u]],root[rs[u]],1,n); ans+=std::min(na,nb); } return 0; } int main() { n=read(); int w=0,now=0; while(w<n) { val[++num]=read(); if(num>1) { while(rs[now]) { now=fa[now]; } ins(now,num); } if(val[num]) { ++w; } else { now=num; } } for(int i=1; i<=num; ++i) { if(val[i]) { build(root[i]=&tnode[++cnt],1,n,val[i]); } } search(1); printf("%lld\n",ans); return 0; }
转载请注明原文地址: https://www.6miu.com/read-2623319.html

最新回复(0)