BZOJ - 3744 Gty的妹子序列 (区间逆序对数,分块)

题目链接

静态区间逆序对数查询,这道题用线段树貌似不好做,可以把区间分成$\sqrt n$块,预处理出两个数组:$sum[i][j]$和$inv[i][j]$,$sum[i][j]$表示前i个块中小于等于j的数的个数,$inv[i][j]$表示第i块与第j块之间的逆序对数,递推搞一下就行。查询的时候中间的部分直接查询,两边多出来的部分暴力计算贡献即可。总复杂度$O(n\sqrt nlogn)$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=5e4+10,sqrtN=226,inf=0x3f3f3f3f;
 5 int a[N],b[N],c[N],n2,in[N],L[sqrtN],R[sqrtN],n,m,sqrtn,nb;
 6 int sum[sqrtN][N],inv[sqrtN][sqrtN];
 7 void add(int u,int x) {for(; u<=n2; u+=u&-u)c[u]+=x;}
 8 int get(int u) {int ret=0; for(; u; u-=u&-u)ret+=c[u]; return ret;}
 9 int main() {
10     scanf("%d",&n),sqrtn=sqrt(n+0.5);
11     for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
12     for(int i=1; i<=n; ++i)b[i-1]=a[i];
13     sort(b,b+n),n2=unique(b,b+n)-b;
14     for(int i=1; i<=n; ++i)a[i]=lower_bound(b,b+n2,a[i])-b+1;
15     for(int i=1; i<=n; ++i) {nb=in[i]=i/sqrtn+1; if(!L[in[i]])L[in[i]]=i; R[in[i]]=i;}
16     for(int i=1; i<=nb; ++i) {
17         for(int j=L[i]; j<=R[i]; ++j)sum[i][a[j]]++;
18         for(int j=2; j<=n; ++j)sum[i][j]+=sum[i][j-1];
19         for(int j=1; j<=n; ++j)sum[i][j]+=sum[i-1][j];
20     }
21     for(int i=1; i<=nb; ++i) {
22         for(int j=R[i]; j>=L[i]; --j)inv[i][i]+=get(a[j]-1),add(a[j],1);
23         for(int j=R[i]; j>=L[i]; --j)add(a[j],-1);
24     }
25     for(int i=1; i<=nb; ++i)
26         for(int j=i+1; j<=nb; ++j) {
27             for(int k=L[j]; k<=R[j]; ++k)inv[i][j]+=(R[j-1]-L[i]+1)-(sum[j-1][a[k]]-sum[i-1][a[k]]);
28             inv[i][j]+=inv[i][j-1]+inv[j][j];
29         }
30     scanf("%d",&m);
31     for(int ans=0; m--;) {
32         int l,r;
33         scanf("%d%d",&l,&r),l^=ans,r^=ans,ans=0;
34         if(in[l]==in[r]) {
35             for(int i=r; i>=l; --i)ans+=get(a[i]-1),add(a[i],1);
36             for(int i=r; i>=l; --i)add(a[i],-1);
37         } else {
38             int lb=in[l]+1,rb=in[r]-1;
39             if(lb<=rb) {
40                 ans+=inv[lb][rb];
41                 for(int i=r; i>=L[in[r]]; --i)ans+=(R[rb]-L[lb]+1)-(sum[rb][a[i]]-sum[lb-1][a[i]]);
42                 for(int i=R[in[l]]; i>=l; --i)ans+=sum[rb][a[i]-1]-sum[lb-1][a[i]-1];
43             }
44             for(int i=r; i>=L[in[r]]; --i)ans+=get(a[i]-1),add(a[i],1);
45             for(int i=R[in[l]]; i>=l; --i)ans+=get(a[i]-1),add(a[i],1);
46             for(int i=r; i>=L[in[r]]; --i)add(a[i],-1);
47             for(int i=R[in[l]]; i>=l; --i)add(a[i],-1);
48         }
49         printf("%d\n",ans);
50     }
51     return 0;
52 }

 

posted @ 2019-04-13 13:05  jrltx  阅读(179)  评论(0编辑  收藏  举报