感觉这题还是不错的……虽然其实算是比较水的题= =
首先分块,令f[i][j]表示第i块到第j块的逆序对数,询问的时候直接计算不完整块与完整块以及不完整块之间的逆序对。
不完整块之间的逆序对直接树状数组暴力求,至于不完整块和完整块的逆序对,我是令s[i]表示前i块的权值前缀和,这样单次查询O(1),可以减小一点常数,代价是空间稍微费了点……
预处理O(nsqrt(n)logn),单次查询O(sqrt(n)logn),空间O(nsqrt(n)),好吧我懒得算如何调节块大小来降低复杂度了,于是就随便找了个233当的块大小= =
细节并不多,然而因为各种脑残错误调了半天才敢交,又因为没看见要离散化和没加强制在线RE两次,真是废了……
1 /************************************************************** 2 Problem: 3744 3 User: hzoier 4 Language: C++ 5 Result: Accepted 6 Time:9688 ms 7 Memory:49700 kb 8 ****************************************************************/ 9 10 #include<cstdio> 11 #include<cstring> 12 #include<algorithm> 13 using namespace std; 14 const int maxn=50010,B=233,maxb=245; 15 void add(int,int); 16 int query(int); 17 int a[maxn],b[maxn],id[maxn],L[maxb]={0},R[maxb]={0},cntb,f[maxb][maxb]={{0}},s[maxb][maxn]={{0}},c[maxn]={0}; 18 int n,m,l,r,lb,rb,ans=0; 19 int main(){ 20 scanf("%d",&n); 21 for(int i=1;i<=n;i++){ 22 scanf("%d",&a[i]); 23 cntb=id[i]=(i-1)/B+1; 24 if(!L[id[i]])L[id[i]]=i; 25 R[id[i]]=i; 26 } 27 copy(a+1,a+n+1,b+1); 28 sort(b+1,b+n+1); 29 for(int i=1;i<=n;i++)s[id[i]][a[i]=lower_bound(b+1,b+n+1,a[i])-b]++; 30 for(int i=1;i<=cntb;i++){ 31 for(int j=1;j<=n;j++)s[i][j]+=s[i-1][j]; 32 for(int j=i;j<=cntb;j++){ 33 for(int k=L[j];k<=R[j];k++){ 34 f[i][j]+=query(a[k]+1); 35 add(a[k],1); 36 } 37 f[i][j]+=f[i][j-1]; 38 } 39 memset(c,0,sizeof(c)); 40 } 41 for(int i=1;i<=cntb;i++)for(int j=1;j<=n;j++)s[i][j]+=s[i][j-1]; 42 scanf("%d",&m); 43 while(m--){ 44 scanf("%d%d",&l,&r); 45 l^=ans;r^=ans; 46 if(id[l]>=id[r]-1){ 47 ans=0; 48 for(int i=l;i<=r;i++){ 49 ans+=query(a[i]+1); 50 add(a[i],1); 51 } 52 for(int i=l;i<=r;i++)add(a[i],-1); 53 } 54 else{ 55 lb=id[l]+1;rb=id[r]-1; 56 ans=f[lb][rb]; 57 for(int i=l;i<L[lb];i++){ 58 ans+=query(a[i]+1)+s[rb][a[i]-1]-s[lb-1][a[i]-1]; 59 add(a[i],1); 60 } 61 for(int i=R[rb]+1;i<=r;i++){ 62 ans+=query(a[i]+1)+(s[rb][n]-s[rb][a[i]])-(s[lb-1][n]-s[lb-1][a[i]]); 63 add(a[i],1); 64 } 65 for(int i=l;i<L[lb];i++)add(a[i],-1); 66 for(int i=R[rb]+1;i<=r;i++)add(a[i],-1); 67 } 68 printf("%d\n",ans); 69 } 70 return 0; 71 } 72 void add(int x,int d){ 73 while(x){ 74 c[x]+=d; 75 x&=x-1; 76 } 77 } 78 int query(int x){ 79 int ans=0; 80 while(x<=n){ 81 ans+=c[x]; 82 x+=x&-x; 83 } 84 return ans; 85 }
时间: 2024-10-01 15:52:56