[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 }
View Code

 

posted @ 2016-01-15 14:38  czllgzmzl  阅读(282)  评论(2编辑  收藏  举报