[bzoj3744] Gty的妹子序列

  还是分块>_<

  强制在线求区间逆序。。如果没有空间限制的话显然是树套树?

  分成根号n块,预处理出sum[i][j]表示从第i块的左端,到第j个点 这段区间内的逆序对个数。这部分可以直接树状数组O(n^1.5 logn)

  那么对于每个询问,我们只要考虑左侧的零散节点对答案的贡献了。。

  因此需要快速求出整块以及右侧零散节点插入后的树状数组。

  再预处理出t[i][]表示前i块的数  的树状数组。。所以整块整块的树状数组就可以由前缀和得出。

  再暴力插入右侧零散节点。。最后左侧零散节点就边插边统计了。。

  总的时间复杂度O(n^1.5 logn)

  块的大小就是根号n吧。。。不过具体来说比根号n小一些比较优

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define ll long long
 6 using namespace std;
 7 const int maxn=50003;
 8 struct zs{
 9     int v;unsigned short pos;
10 }b[maxn];int cnt;
11 int id[maxn],mp[maxn],l[305],r[305];
12 int sm[305][maxn],t[305][maxn],tt[maxn];
13 int i,j,k,n,m,x,y,kuai,la;
14   
15 int ra,fh;char rx;
16 inline int read(){
17     rx=getchar(),fh=1,ra=0;
18     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
19     if(rx=='-')fh=-1,rx=getchar();
20     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
21 }
22   
23 bool cmp(zs a,zs b){return a.v<b.v;}
24 inline int query(int x,int y){
25     register int j;int i,ans=0,k=id[y]-1;
26     if(x==l[id[x]])return sm[id[x]][y];
27     if(id[x]==id[y]){
28         for(i=x;i<=y;i++){
29             for(j=mp[i],ans+=i-x;j;j-=j&-j)ans-=tt[j];
30             for(j=mp[i];j<=cnt;j+=j&-j)++tt[j];
31         }
32         for(i=x;i<=y;i++)
33             for(j=mp[i];j<=cnt&&tt[j]!=0;j+=j&-j)tt[j]=0;
34         return ans;
35     }
36     ans=sm[id[x]+1][y];
37     for(i=y;i>=l[id[y]];i--)for(j=mp[i];j<=cnt;j+=j&-j)++tt[j];
38     if(id[x]+1<id[y])
39         for(i=r[id[x]];i>=x;i--){
40             for(j=mp[i]-1;j;j-=j&-j)ans+=tt[j]+t[k][j]-t[id[x]][j];
41             for(j=mp[i];j<=cnt;j+=j&-j)++tt[j];
42         }
43     else{
44         for(i=r[id[x]];i>=x;i--){
45             for(j=mp[i]-1;j;j-=j&-j)ans+=tt[j];
46             for(j=mp[i];j<=cnt;j+=j&-j)++tt[j];
47         }
48     }
49     for(i=r[id[x]];i>=x;i--)for(j=mp[i];j<=cnt&&tt[j]!=0;j+=j&-j)tt[j]=0;
50     for(i=y;i>=l[id[y]];i--)for(j=mp[i];j<=cnt&&tt[j]!=0;j+=j&-j)tt[j]=0;
51     return ans;
52 }
53 int main(){
54     n=read();kuai=min(n,166);//kuai=1;
55     for(i=1;i<=n;i++)b[i].v=read(),b[i].pos=i,id[i]=(i+kuai-1)/kuai;
56       
57     for(i=1;i<=id[n];i++)l[i]=(i-1)*kuai+1,r[i]=i<id[n]?kuai*i:n;
58     sort(b+1,b+1+n,cmp);
59     for(i=1;i<=n;mp[b[i].pos]=cnt,i++)
60         if(b[i].v!=b[i-1].v||i==1)cnt++;
61     for(i=1;i<=id[n];i++){
62         for(j=l[i];j<=r[i];j++)++t[i][mp[j]];
63         for(j=1;j<=cnt;t[i][j]+=t[i-1][j],j++)if(j+(j&-j)<=cnt)t[i][j+(j&-j)]+=t[i][j];
64     }
65      
66     for(i=1;i<=id[n];i++){
67         if(i>1)memset(tt,0,(cnt+1)<<2);
68         for(j=l[i];j<=n;j++){
69             for(sm[i][j]=sm[i][j-1]+j-l[i],k=mp[j];k;k-=k&-k)sm[i][j]-=tt[k];
70             for(k=mp[j];k<=cnt;k+=k&-k)++tt[k];
71         }
72     }memset(tt,0,(cnt+1)<<2);
73      
74     for(m=read();m;m--)
75         x=read()^la,y=read()^la,
76         la=query(x,y),printf("%d\n",la);
77     return 0;
78 }
View Code

  一开始没删调试挂了两发= =我果然是傻逼QAQ

posted @ 2016-04-11 19:34  czllgzmzl  阅读(193)  评论(0编辑  收藏  举报