bzoj2821 作诗(Poetize)分块+二分

预处理的d[i][j]为第i块到第j点的答案

块外的暴力

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
#define maxn 100100
#define maxs 320
int S,T;
int n,m,c;
vector<int> col[maxn];
int a[maxn];
int le[maxs],ri[maxs];
int d[maxs][maxn];
int rec,cas;
int op[maxs],cc[maxn];
int lab[maxn],num;
int ask(int x,int y){
int mid,l=-1,r=col[y].size();
while(l+1!=r){
mid=(l+r)>>1;
if(col[y][mid]>x)r=mid;
else l=mid;
}
return r;
}
inline int sum(int x,int y,int z){
return ask(y,z)-ask(x-1,z);
}
int in[maxn];
inline void put(int x){
if(lab[a[x]]!=cas){
op[++num]=a[x];
lab[a[x]]=cas;
cc[a[x]]=0;
}
cc[a[x]]++;
}
int query(int x,int y){
int ans=0,ss;
int l=in[x]+1;
num=0;
if(in[x]==in[y])for(int i=x;i<=y;i++)put(i);
else for(int i=x;i<=ri[in[x]];i++)put(i);
if(in[x]!=in[y]){
ans=d[l][y];
for(int i=1;i<=num;i++){
ss=sum(le[l],y,op[i]);
if(cc[op[i]]&1){
if(ss&1)ans++;
else if(ss)ans--;
}else{
if(ss&1);
else if(!ss)ans++;
}
}
}else for(int i=1;i<=num;i++)if(!(cc[op[i]]&1))ans++;
return ans;
}
int main(){
scanf("%d%d%d",&n,&c,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
col[a[i]].push_back(i);
}
T=sqrt(n);
if(n-T*T>(T+1)*(T+1)-n)T++;
int now=0;
for(int i=1;i<=n;i++,now--){
if(!now)S++,now=T,le[S]=i,ri[S-1]=i-1;
in[i]=S;
}
ri[S]=n;
for(int i=1;i<=S;i++){
memset(cc,0,sizeof(cc));
rec=0;
for(int j=le[i];j<=n;j++){
if(cc[a[j]]){if(cc[a[j]]&1)rec++;else rec--;}
cc[a[j]]++;
d[i][j]=rec;
}
}
int lans=0;
for(cas=1;cas<=m;cas++){
int x,y;
scanf("%d%d",&x,&y);
x=(x+lans)%n+1;
y=(y+lans)%n+1;
if(x>y)swap(x,y);
lans=query(x,y);
printf("%d\n",lans);
}
}

posted @ 2014-03-26 19:38  wangyucheng  阅读(240)  评论(0编辑  收藏  举报