分块~好麻烦
就像区间众数那题一样来
用vector+二分来判区间每个数出现的个数
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> using namespace std; int n,a[110000]; int block,st[110000]; int f[410][410]; int tim,ti[110000];bool v[101000]; vector<int>vec[110000];int le[110000]; int ifodd(int x,int y,int m) { if(x>y)return 0; int l=0,r=le[m]-1,as1=0; while(l<=r) { int mid=(l+r)/2; if(vec[m][mid]<=x) { as1=mid+1; l=mid+1; } else r=mid-1; } l=0,r=le[m]-1;int as2=0; while(l<=r) { int mid=(l+r)/2; if(vec[m][mid]<=y) { as2=mid+1; l=mid+1; } else r=mid-1; } return (as2==as1)?(-1):((as2-as1)&1); } int main() { freopen("poetize.in","r",stdin); freopen("poetize.out","w",stdout); int Q,C; scanf("%d%d%d",&n,&C,&Q); block=(int(sqrt(double(n+1))))+1; memset(le,0,sizeof(le)); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); st[i]=(i-1)/block+1; vec[a[i]].push_back(i);le[a[i]]++; } tim=0; memset(ti,0,sizeof(ti)); for(int i=1;i<=block;i++) { int j=i,cc=0; tim++; int be=(i-1)*block+1; for(int k=be;k<=n;k++) { if(st[k]!=st[k-1]&&k!=be) { f[i][j]=cc; j++; } if(tim!=ti[a[k]]) { ti[a[k]]=tim; v[a[k]]=0;cc++; } v[a[k]]^=1; if(v[a[k]]==0)cc++; else cc--; } f[i][j]=cc; } //---------------init--------------------- int l,r,ans=0; while(Q--) { scanf("%d%d",&l,&r); l=(l+ans)%n+1,r=(r+ans)%n+1; if(l>r)swap(l,r); ans=0; tim++; if(st[l]==st[r]) { for(int k=l;k<=r;k++) { if(tim!=ti[a[k]]) { ti[a[k]]=tim; v[a[k]]=0;ans++; } v[a[k]]^=1; if(v[a[k]]==0)ans++; else ans--; } } else { if(st[l]+1<=st[r]-1)ans=f[st[l]+1][st[r]-1]; for(int k=l;k<=st[l]*block;k++) { if(tim!=ti[a[k]]) { ti[a[k]]=tim; int d=ifodd(st[l]*block,(st[r]-1)*block,a[k]); if(d<=0) { if(d==-1)ans++; v[a[k]]=0; } else v[a[k]]=1; } v[a[k]]^=1; if(v[a[k]]==0)ans++; else ans--; } for(int k=(st[r]-1)*block+1;k<=r;k++) { if(tim!=ti[a[k]]) { ti[a[k]]=tim; int d=ifodd(st[l]*block,(st[r]-1)*block,a[k]); if(d<=0) { if(d==-1)ans++; v[a[k]]=0; } else v[a[k]]=1; } v[a[k]]^=1; if(v[a[k]]==0)ans++; else ans--; } } printf("%d ",ans); } return 0; }