类似上题的做法,f[i][j]表示第i块到第j块出现偶数次的数有多少个,然后调整一下。
复杂度n√nlogn。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define maxn 100050 using namespace std; int n,c,m,a[maxn],cnt[maxn],blo[maxn],ret=0,f[2050][2050],l,r,len,st[maxn],lastans=0; int flag[maxn],base[maxn],times=0; int l1,r1,l2,r2,s[maxn],s1[maxn],s2[maxn],top=0; vector <int> v[maxn]; int read() { char ch;int data=0; while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') { data=data*10+ch-'0'; ch=getchar(); } return data; } void build() { ret=1; for (int i=1;i<=n;i++) { blo[i]=ret;v[a[i]].push_back(i); if (!(i%len) && i!=n) {st[ret]=i;ret++;} } if (n%len) st[ret]=n; for (int i=1;i<=ret;i++) { int t1=0,t2=0;memset(cnt,0,sizeof(cnt)); for (int j=(i-1)*len+1;j<=n;j++) { cnt[a[j]]++; if (cnt[a[j]]==1) t2++; else if (cnt[a[j]]&1) t1--,t2++; else t1++,t2--; if (!(j%len)) f[i][j/len]=t1; } if (n%len) f[i][ret]=t1; } } int find_(int l,int r,int x) { int ans1=-1,ans2=-1,left,right; left=0;right=v[x].size()-1; while (left<=right) { int mid=(left+right)>>1; if (v[x][mid]>=l) {ans1=mid;right=mid-1;} else left=mid+1; } left=0;right=v[x].size()-1; while (left<=right) { int mid=(left+right)>>1; if (v[x][mid]<=r) {ans2=mid;left=mid+1;} else right=mid-1; } if ((ans1==-1) || (ans2==-1)) return 0; return ans2-ans1+1; } int ask(int l,int r) { times++; if (blo[l]+1>blo[r]-1) { int t1=0,t2=0; for (int i=l;i<=r;i++) { if (flag[a[i]]!=times) {flag[a[i]]=times;t2++;base[a[i]]=cnt[a[i]];cnt[a[i]]++;} else { cnt[a[i]]++; if ((cnt[a[i]]-base[a[i]])&1) t1--,t2++; else t1++,t2--; } } return t1; } else { top=0;l1=l;r1=r;l2=st[blo[l]]+1;r2=st[blo[r]-1];int ret=f[blo[l]+1][blo[r]-1]; for (int i=l;i<=st[blo[l]];i++) s[++top]=a[i]; for (int i=st[blo[r]-1]+1;i<=r;i++) s[++top]=a[i]; sort(s+1,s+top+1);top=unique(s+1,s+top+1)-s-1; for (int i=1;i<=top;i++) s1[i]=find_(l1,r1,s[i]),s2[i]=find_(l2,r2,s[i]); for (int i=1;i<=top;i++) { if (!s2[i]) { if (s1[i]&1) continue; ret++; } else { if ((s2[i]&1) && (!(s1[i]&1))) ret++; if ((!(s2[i]&1)) && (s1[i]&1)) ret--; } } return ret; } } int main() { n=read();c=read();m=read();len=80; for (int i=1;i<=n;i++) a[i]=read(); build(); for (int i=1;i<=m;i++) { l=read();r=read(); l=(l+lastans)%n+1;r=(r+lastans)%n+1; if (l>r) swap(l,r); lastans=ask(l,r);printf("%d\n",lastans); } return 0; }