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 }