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

题目分析:

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

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

令分块大小为$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[p]) 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 }

 

posted @ 2018-08-30 09:34  menhera  阅读(243)  评论(0编辑  收藏  举报