bzoj3744 Gty的妹子序列

我是萌萌的传送门

感觉这题还是不错的……虽然其实算是比较水的题= =

首先分块,令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 }
View Code

 

posted @ 2016-12-30 19:36  AntiLeaf  阅读(139)  评论(0编辑  收藏  举报