传送门:
http://www.lydsy.com/JudgeOnline/problem.php?id=2821
蒟蒻的分块第一题,常数T成翔,
蒟蒻没优化前跑n=m=c=1e5的大点4000+ms,标程2000+ms
加读入优化3500+ms
删掉不必要的memset 3000+ms
然后把vis数组改成记录当前方案数而不是01,再去一个memset, 2184ms
交到bzoj终于过了……
/*
ID:zky
OJ:BZOJ
Index:2821
Language:C++
*/
#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<ctime>
using namespace std;
const int maxn=int(1e5)+11;
const int sqrtn=320;
int n,m,t;
int a[maxn],b[maxn],c[maxn],vis[maxn],ans=0;
int st[maxn],ed[maxn],s[sqrtn],e[sqrtn];
int d[sqrtn][sqrtn],q[maxn];
int sqrn,bksz,tot;
inline int calc(int k,int x,int y){
if(x>y)return 0;
int l,r,mid;
l=st[k];r=ed[k];
while(l<r){
mid=l+r>>1;
if(b[mid]<x)
l=mid+1;
else
r=mid;
}
if(b[l]>=x)l--;
x=l;
l=st[k];r=ed[k];
while(l<r){
mid=l+r>>1;
if(b[mid]>y)
r=mid;
else
l=mid+1;
}
if(b[l]>y)l--;
y=l;
return y-x;
}
int getint(){
int res=0;
int ok=0;
char ch;
while(1){
ch=getchar();
if(ch>='0'&&ch<='9'){
res*=10;
res+=ch-'0';
ok=1;
}else
if(ok)break;
}
return res;
}
int main(){
scanf("%d%d%d",&n,&t,&m);
for(int i=1;i<=n;i++)a[i]=getint();
for(int i=1;i<=n;i++)c[a[i]]++;
for(int i=1;i<=t;i++){
st[i]=tot+1;
tot+=c[i];
ed[i]=tot;
}
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)
b[st[a[i]]+c[a[i]]]=i,c[a[i]]++;
sqrn=int(sqrt(n));bksz=n/sqrn;
for(int i=1;i<=sqrn;i++){
s[i]=(i-1)*bksz+1;
e[i]=i*bksz;
}
if(e[sqrn]<n){
sqrn++;
s[sqrn]=e[sqrn-1]+1;
e[sqrn]=n;
}
for(int i=1;i<=sqrn;i++){
memset(c,0,sizeof(c)); ans=0;
for(int j=i;j<=sqrn;j++){
for(int k=s[j];k<=e[j];k++){
c[a[k]]++;
if(c[a[k]]>1&&(c[a[k]]&1)) ans--;
else if((c[a[k]]&1)==0) ans++;
}
d[i][j]=ans;
}
}
ans=0;
for(int stp=1;stp<=m;stp++){
int x,y,l,r;
x=getint();y=getint();
x=(x+ans)%n+1;y=(y+ans)%n+1;
if(x>y)swap(x,y);
int *esqrn = e + sqrn;
for(int i=1;i<=sqrn;i++)if(e[i]>=x){l=i;break;}
for(int i=sqrn;i>=1;i--)if(s[i]<=y){r=i;break;}
ans=d[l+1][r-1];
if(l==r){
for(int i=x;i<=y;i++){
if(vis[a[i]]!=stp){
vis[a[i]]=stp;
c[a[i]]=1;
}else{
c[a[i]]++;
if(c[a[i]]&1)ans--;else ans++;
}
}
printf("%d\n",ans);
continue;
}
int cnt=0;
for(int i=x;i<=e[l];i++){
if(vis[a[i]]!=stp){
vis[a[i]]=stp;
c[a[i]]=1;
q[++cnt]=a[i];
}else c[a[i]]++;
}
for(int i=s[r];i<=y;i++){
if(vis[a[i]]!=stp){
vis[a[i]]=stp;
c[a[i]]=1;
q[++cnt]=a[i];
}else c[a[i]]++;
}
for(int i=1;i<=cnt;i++){
int k=calc(q[i],s[l+1],e[r-1]);
if(k==0){
if((c[q[i]]&1)||!c[q[i]])ans+=0;else ans+=1;
}else
if((k&1)&&(c[q[i]]&1))ans++;
else if(!(k&1)&&(c[q[i]]&1))ans--;
}
printf("%d\n",ans);
}
return 0;
}