您的位置:首页 > 其它

BZOJ3744 : Gty的妹子序列

2014-11-14 15:36 127 查看
分块预处理出[i,j]块内的答案以及数字出现次数,查询时向两边转移,用树状数组维护,复杂度$O((n+m)\sqrt{n}\log n)$。

#include<cstdio>
#include<algorithm>
const int N=50010,K=226;
int n,m,l,r,i,j,k,size,block,a
,b
,pos
,st[K],en[K],ans[K][K],ap[K]
,T,now,all,bit
,vis
,last;
inline void read(int&a){char ch;while(!(((ch=getchar())>='0')&&(ch<='9')));a=ch-'0';while(((ch=getchar())>='0')&&(ch<='9'))(a*=10)+=ch-'0';}
inline int lower(int x){
int l=1,r=n,mid,t;
while(l<=r)if(b[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
return t;
}
inline void add(int x){for(;x<=n;x+=x&-x)if(vis[x]!=T)vis[x]=T,bit[x]=1;else bit[x]++;}
inline int sum(int x){int t=0;for(;x;x-=x&-x)if(vis[x]==T)t+=bit[x];return t;}
inline int ask(int l,int r){
T++;
if(pos[l]==pos[r]){
now=0;
for(;r>=l;r--)now+=sum(a[r]-1),add(a[r]);
return now;
}
now=ans[pos[l]+1][pos[r]-1],all=st[pos[r]]-en[pos[l]]-1;
for(i=en[pos[l]];i>=l;i--)now+=sum(a[i]-1)+ap[pos[r]-1][a[i]-1]-ap[pos[l]][a[i]-1],add(a[i]),all++;
for(i=st[pos[r]];i<=r;i++)now+=all-sum(a[i])-ap[pos[r]-1][a[i]]+ap[pos[l]][a[i]],add(a[i]),all++;
return now;
}
int main(){
read(n);
for(i=1;i<=n;i++)read(a[i]),b[i]=a[i];
for(std::sort(b+1,b+n+1),i=1;i<=n;i++)a[i]=lower(a[i]);
for(;size*size<n;size++);
for(i=1;i<=n;i++)pos[i]=(i-1)/size+1;
for(block=pos
,i=1;i<=block;i++)st[i]=size*(i-1)+1;
for(en[block]=n,i=block-1;i;i--)en[i]=st[i+1]-1;
for(i=1;i<=block;i++){
now=all=0,T++;
for(j=1;j<=n;j++)ap[i][j]=ap[i-1][j];
for(j=i;j<=block;ans[i][j++]=now)for(k=st[j];k<=en[j];k++)now+=all-sum(a[k]),add(a[k]),all++,ap[j][a[k]]++;
}
for(i=1;i<=block;i++)for(j=2;j<=n;j++)ap[i][j]+=ap[i][j-1];
read(m);
while(m--)read(l),read(r),l^=last,r^=last,printf("%d\n",last=ask(l,r));
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: