[bzoj2141]排队
树套树。。我写了线段树套treap= =外层线段树表示各段区间,每段区间内按权值大小开个treap
设数列为map[],一开始求出逆序对个数。
每次假设交换l和r这两位置的数,答案就要减去[l+r,r-1]中比map[l]小的数的个数,再减去[l+1,r-1]中比map[r]大的数的个数,
加上[l+1,r-1]中比map[l]大的数的个数,再加上[l+1,r-1]中比map[r]小的数的个数。。最后看下map[l]和map[r]的大小关系
挺显然的。。交换的时候就在l和r位置所在的线段树节点里面改(删掉原来的,插入交换后的数)
一开始外层的zkw线段树写挂了= =
感觉树套树空间问题各种蛋疼。。。每次都要算个半天= =
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=26233; 7 int l[maxn*20],r[maxn*20],sz[maxn*20],w[maxn*20],num[maxn*20],rnd[maxn*20],tot; 8 int rt[66233],size; 9 int mp[maxn]; 10 int i,j,n,m,ans,L,R; 11 12 int ra;char rx; 13 inline int read(){ 14 rx=getchar(),ra=0; 15 while(rx<'0'||rx>'9')rx=getchar(); 16 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 17 } 18 19 20 inline void upd(int x){sz[x]=sz[l[x]]+w[x]+sz[r[x]];} 21 inline void lturn(int &x,int R){ 22 r[x]=l[R],l[R]=x,sz[R]=sz[x],upd(x),x=R; 23 } 24 inline void rturn(int &x,int L){ 25 l[x]=r[L],r[L]=x,sz[L]=sz[x],upd(x),x=L; 26 } 27 void ins(int &x,int v){ 28 if(!x){x=++tot,rnd[x]=rand(),sz[x]=w[x]=1,num[x]=v;return;} 29 sz[x]++; 30 if(v==num[x])w[x]++;else 31 if(v<num[x]){ 32 ins(l[x],v); 33 if(rnd[l[x]]<rnd[x])rturn(x,l[x]); 34 }else{ 35 ins(r[x],v); 36 if(rnd[r[x]]<rnd[x])lturn(x,r[x]); 37 } 38 } 39 void del(int &x,int v){ 40 if(num[x]==v){ 41 if(w[x]>1)w[x]--,sz[x]--;else 42 if(!(l[x]&&r[x]))x=l[x]|r[x];else 43 if(rnd[l[x]]<rnd[r[x]])rturn(x,l[x]),del(x,v); 44 else lturn(x,r[x]),del(x,v); 45 }else if(v<num[x])sz[x]--,del(l[x],v); 46 else sz[x]--,del(r[x],v); 47 } 48 int smnum(int x,int v){ 49 if(!x)return 0; 50 if(v<num[x])return smnum(l[x],v); 51 else if(v==num[x])return sz[l[x]]+smnum(r[x],v); 52 else return sz[l[x]]+w[x]+smnum(r[x],v); 53 } 54 int binum(int x,int v){ 55 if(!x)return 0; 56 if(v>num[x])return binum(r[x],v); 57 else if(v==num[x])return sz[r[x]]+binum(l[x],v); 58 else return sz[r[x]]+w[x]+binum(l[x],v); 59 } 60 61 int query(int l,int r,int v,bool big){ 62 if(l>r)return 0; 63 l+=size,r+=size; 64 if(l==r)return big?binum(rt[l],v):smnum(rt[l],v); 65 66 int sum=big?(binum(rt[l],v)+binum(rt[r],v)):(smnum(rt[l],v)+smnum(rt[r],v)); 67 for(;l^r^1;l>>=1,r>>=1){ 68 if(!(l&1))sum+=big?binum(rt[l^1],v):smnum(rt[l^1],v); 69 if(r&1)sum+=big?binum(rt[r^1],v):smnum(rt[r^1],v); 70 } 71 return sum; 72 } 73 74 int main(){ 75 n=read(); 76 for(size=1;size<n;size<<=1);size--; 77 for(i=1;i<=n;i++){ 78 mp[i]=read(); 79 for(j=i+size;j>1;j>>=1)if(j&1)ans+=binum(rt[j^1],mp[i]); 80 for(j=i+size;j;j>>=1)ins(rt[j],mp[i]); 81 } 82 printf("%d\n",ans); 83 m=read(); 84 while(m--){ 85 L=read(),R=read();if(L>R)swap(L,R); 86 if(L==R){printf("%d\n",ans);continue;} 87 ans-=query(L+1,R-1,mp[L],0)+query(L+1,R-1,mp[R],1); 88 ans+=query(L+1,R-1,mp[L],1)+query(L+1,R-1,mp[R],0); 89 if(mp[L]<mp[R])ans++;else if(mp[L]>mp[R])ans--; 90 for(j=L+size;j;j>>=1)del(rt[j],mp[L]); 91 for(j=R+size;j;j>>=1)del(rt[j],mp[R]); 92 for(j=R+size;j;j>>=1)ins(rt[j],mp[L]); 93 for(j=L+size;j;j>>=1)ins(rt[j],mp[R]); 94 swap(mp[L],mp[R]); 95 printf("%d\n",ans); 96 } 97 return 0; 98 }