BZOJ3744 Gty的妹子序列(分块+树状数组)

题意

询问区间内逆序对数  强制在线

1<=n<=50000 1<=m<=50000

题解

两个预处理f[i][j]为块i到j的逆序对数,s[i][j]前i块≤j的有多少个
边角余料用个树状数组就行了

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=50100;
 8 int n,Block,a[N],b[N],block[N],R[500],L[500],f[500][500],tr[500][N],m,ans;
 9 int lowbit(int x){
10     return x&-x;
11 }
12 void add(int id,int x,int w){
13     for(int i=x;i<=n;i+=lowbit(i)){
14         tr[id][i]+=w;
15     }
16 }
17 int getsum(int id,int x){
18     int tmp=0;
19     for(int i=x;i;i-=lowbit(i)){
20         tmp+=tr[id][i];
21     }
22     return tmp;
23 }
24 int main(){
25     scanf("%d",&n);
26     Block=sqrt(n);
27     for(int i=1;i<=n;i++){
28         scanf("%d",&a[i]);
29         b[i]=a[i];
30         block[i]=(i-1)/Block+1;
31         if(!L[block[i]])L[block[i]]=i;
32         R[block[i]]=i;
33     }
34     sort(b,b+1+n);
35     int tot=unique(b+1,b+1+n)-b-1;
36     for(int i=1;i<=n;i++){
37         a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
38     }
39     for(int i=1;i<=block[n];i++){
40         for(int j=L[i];j<=n;j++){
41             add(i,a[j],1);
42         } 
43     }
44     for(int i=1;i<=block[n];i++){
45         int tot=0;
46         for(int j=L[i];j<=n;j++){
47             add(0,a[j],1);
48             tot+=getsum(0,n)-getsum(0,a[j]);
49             f[i][block[j]]=tot;
50         }
51         for(int j=L[i];j<=n;j++){
52             add(0,a[j],-1);
53         }
54     }
55     scanf("%d",&m);
56     while(m--){
57         int l,r;
58         scanf("%d%d",&l,&r);
59         l=l^ans;r=r^ans;
60         if(l>r)swap(l,r);
61         if(l==0||r==0||l>n||r>n)continue;
62         if(block[l]+1>=block[r]){
63             ans=0;
64             for(int i=l;i<=r;i++){
65                 add(0,a[i],1);
66                 ans+=getsum(0,n)-getsum(0,a[i]);
67             }
68             for(int i=l;i<=r;i++){
69                 add(0,a[i],-1);
70             }
71         } 
72         else{
73             ans=f[block[l]+1][block[r]-1];
74             int size=L[block[r]]-R[block[l]]-1;
75         //    cout<<ans<<" "<<size<<"sdjksd"<<endl;
76             for(int i=l;i<=R[block[l]];i++){
77                 ans+=getsum(block[l]+1,a[i]-1)-getsum(block[r],a[i]-1);
78                 add(0,a[i],1);
79                 ans+=getsum(0,n)-getsum(0,a[i]);
80             }
81             for(int i=L[block[r]];i<=r;i++){
82                 ans+=size-(getsum(block[l]+1,a[i])-getsum(block[r],a[i]));
83                 add(0,a[i],1);
84                 ans+=getsum(0,n)-getsum(0,a[i]);
85             }
86             for(int i=l;i<=R[block[l]];i++){
87                 add(0,a[i],-1);
88             }
89             for(int i=L[block[r]];i<=r;i++){
90                 add(0,a[i],-1);
91             }        
92         }
93         printf("%d\n",ans);
94     }
95     return 0;
96 }

 

posted @ 2018-08-17 22:24  Xu-daxia  阅读(160)  评论(0编辑  收藏  举报