您的位置:首页 > 其它

BZOJ3787 gty的文艺妹子序列 【树状数组】【分块】

2018-08-30 09:34 471 查看

题目分析:

首先这种乱七八糟的题目就分块。然后考虑逆序对的统计。

一是块内的,二是块之间的,三是一个块内一个块外,四是都在块外。

令分块大小为$S$。

块内的容易维护,单次维护时间是$O(S)$。

块之间的有两种维护方法,一种是在块内维持有序,那么修改的时候进行一次插排,查询的时候枚举每一块,然后二分查找;另一种是利用下面所述的另一个数组来做块内统计。第一种方法的时间是$O(S+\frac{n}{S}\log S)$;第二种是$O(\frac{n}{S}logn)$.这里我们需要用树状数组维护,但是树状数组带的$\log$与查找是独立的。

一个在块内一个在块外的通过枚举块外的,然后利用数组$f[i][j]$记录$1 \sim i$块小于等于$j$的数的个数,这里用树状数组维护前缀和。时间复杂度是$O(S \log n)$.

最后一部分单独提取出来求逆序对,时间$O(SlogS)$.

那么$O(Slogn) = O(\frac{n}{S}logn)$可以解得$S = O(\sqrt{n})$.

所以这样做的时间复杂度是$O(n\sqrt{n}logn)$

代码:

 

1 #include<bits/stdc++.h>
2 using namespace std;
3
4 const int srt = 250;
5 const int maxn = 50100;
6
7 int n,m;
8 int c[srt+5][maxn],inside[maxn],con[srt+5][srt+5];
9 int a[maxn],ord[maxn];
10
11 int lowbit(int x){return x&-x;}
12
13 void add(int now,int dr,int om){while(now <= n)c[om][now]+=dr,now+=lowbit(now);}
14 int query(int now,int om){
15     int ans = 0;
16     while(now){ans += c[om][now]; now -= lowbit(now);}
17     return ans;
18 }
19 void Add(int now,int dr,int om){while(now<=n/srt+1){con[om][now]+=dr;now += lowbit(now);}}
20 int Query(int now,int om){
21     int ans = 0;
22     while(now){ans += con[om][now]; now -= lowbit(now);}
23     return ans;
24 }
25
26 void read(){
27     scanf("%d",&n);
28     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
29     scanf("%d",&m);
30 }
31
32 void init(){
33     for(int i=1,cnt=1;i<=n;i+=srt,cnt++){
34     memset(c[0],0,sizeof(c[0]));
35     for(int j=srt-1;j>=0;j--){
36         if(j+i > n) continue;
37         inside[cnt] += query(a[i+j]-1,0);
38         add(a[i+j],1,0);
39     }
40     }
41     for(int i=1;(i-1)*srt+1<=n;i++){
42     memset(c[0],0,sizeof(c[0]));
43     for(int j=(i-1)*srt+1;j<=min(n,i*srt);j++) add(a[j],1,0);
44     for(int j=i+1;(j-1)*srt+1<=n;j++){
45         for(int k=(j-1)*srt+1;k<=min(n,j*srt);k++)
46         con[i][j] += query(n,0)-query(a[k],0);
47     }
48     }
49     for(int i=1;(i-1)*srt+1<=n;i++){
50     int j; for(j=i+1;(j-1)*srt+1<=n;j++);
51     for(;j>i;j--){ int z = con[i][j]; con[i][j] = 0; Add(j,z,i); }
52     for(int j=(i-1)*srt+1;j<=min(n,i*srt);j++){
53         for(int k=i;(k-1)*srt+1<=n;k++) add(a[j],1,k);
54     }
55     }
56 }
57
58 void work(){
59     int lastans = 0;memset(c[0],0,sizeof(c[0]));
60     for(int i=1;i<=m;i++){
61     int pv; scanf("%d",&pv);
62     if(pv == 0){
63         int l,r; scanf("%d%d",&l,&r); l^=lastans; r^=lastans;
64         if(r-l < srt){
65         int ans = 0;
66         for(int j=r;j>=l;j--){ans += query(a[j]-1,0);add(a[j],1,0);}
67         for(int j=r;j>=l;j--){add(a[j],-1,0);}
68         printf("%d\n",ans);lastans = ans;
69         continue;
70         }
71         int st=1,ed=1;
72         while((st-1)*srt+1 < l)st++; while(ed*srt<=r)ed++;ed--;
73         int ans = 0; for(int j=st;j<=ed;j++)ans += inside[j];
74         for(int j=st;j<=ed;j++){ans += Query(ed,j);}
75         for(int j=l;j%srt!=1;j++)ans+=query(a[j]-1,ed)-query(a[j]-1,st-1);
76         for(int j=ed*srt+1;j<=r;j++){
77         ans += (query(n,ed)-query(n,st-1));
78         ans -= (query(a[j],ed)-query(a[j],st-1));
79         }
80         for(int j=r;j>ed*srt;j--){ans += query(a[j]-1,0); add(a[j],1,0);}
81         for(int j=(st-1)*srt;j>=l;j--){ans+=query(a[j]-1,0);add(a[j],1,0);}
82         for(int j=r;j>ed*srt;j--) add(a[j],-1,0);
83         for(int j=(st-1)*srt;j>=l;j--) add(a[j],-1,0);
84         printf("%d\n",ans);lastans = ans;
85     }else{
86         int p,v; scanf("%d%d",&p,&v);p^=lastans,v ^= lastans;
87         int bel = p/srt+(p%srt!=0);
88         for(int j=(bel-1)*srt+1;j<p;j++){
89         if(a[j] > a

) inside[bel]--; if(a[j] > v) inside[bel]++; 90 } 91 for(int j=p+1;j<=bel*srt;j++){ 92 if(a[j] < a[p]) inside[bel]--; if(a[j] < v) inside[bel]++; 93 } 94 for(int j=1;j<bel;j++){ 95 int z = (srt-query(a[p],j)+query(a[p],j-1)); 96 int zz = (srt-query(v,j)+query(v,j-1)); 97 Add(bel,zz-z,j); 98 } 99 for(int j=bel+1;(j-1)*srt+1<=n;j++){ 100 int z=query(a[p]-1,j)-query(a[p]-1,j-1); 101 int r=query(v-1,j)-query(v-1,j-1); 102 Add(j,r-z,bel); 103 } 104 for(int j=bel;(j-1)*srt+1<=n;j++){add(a[p],-1,j); add(v,1,j);} 105 a[p] = v; 106 } 107 } 108 } 109 110 int main(){ 111 read(); 112 init(); 113 work(); 114 return 0; 115 }

[p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: