BZOJ2821 作诗(分块)
和区间众数几乎一模一样的套路。
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 100010 #define BLOCK 350 int n,m,c,a[N],lastans=0; int block,tot,L[N],R[N],pos[N]; int cnt[N],f[BLOCK][BLOCK],sum[BLOCK][N]; int main() { freopen("bzoj2821.in","r",stdin); freopen("bzoj2821.out","w",stdout); n=read(),c=read(),m=read(); for (int i=1;i<=n;i++) a[i]=read(); block=sqrt(n);tot=n/block+(n%block>0); for (int i=1;i<=n/block;i++) L[i]=(i-1)*block+1,R[i]=(i-1)*block+block; if (n/block<tot) L[tot]=n/block*block+1,R[tot]=n; for (int i=1;i<=tot;i++) { memset(cnt,0,sizeof(cnt)); for (int j=i;j<=tot;j++) { f[i][j]=f[i][j-1]; for (int k=L[j];k<=R[j];k++) { cnt[a[k]]++; if (!(cnt[a[k]]&1)) f[i][j]++; else if (cnt[a[k]]>1) f[i][j]--; } } memcpy(sum[i],sum[i-1],sizeof(sum[i])); for (int j=L[i];j<=R[i];j++) pos[j]=i,sum[i][a[j]]++; } memset(cnt,0,sizeof(cnt)); while (m--) { int x=read(),y=read(); x=(x+lastans)%n+1,y=(y+lastans)%n+1; if (x>y) swap(x,y); int num=0; if (pos[x]==pos[y]) { for (int i=x;i<=y;i++) { cnt[a[i]]++; if (!(cnt[a[i]]&1)) num++; else if (cnt[a[i]]>1) num--; } for (int i=x;i<=y;i++) cnt[a[i]]--; } else { num=f[pos[x]+1][pos[y]-1]; for (int i=x;i<=R[pos[x]];i++) { cnt[a[i]]++; if (!(cnt[a[i]]+sum[pos[y]-1][a[i]]-sum[pos[x]][a[i]]&1)) num++; else if (cnt[a[i]]+sum[pos[y]-1][a[i]]-sum[pos[x]][a[i]]>1) num--; } for (int i=L[pos[y]];i<=y;i++) { cnt[a[i]]++; if (!(cnt[a[i]]+sum[pos[y]-1][a[i]]-sum[pos[x]][a[i]]&1)) num++; else if (cnt[a[i]]+sum[pos[y]-1][a[i]]-sum[pos[x]][a[i]]>1) num--; } for (int i=x;i<=R[pos[x]];i++) cnt[a[i]]--; for (int i=L[pos[y]];i<=y;i++) cnt[a[i]]--; } lastans=num; printf("%d\n",num); } return 0; }