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 }