1. 程式人生 > >BZOJ2821 作詩(分塊)

BZOJ2821 作詩(分塊)

span -o 一模一樣 sin include pre getch pan ostream

和區間眾數幾乎一模一樣的套路。

// 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; }

BZOJ2821 作詩(分塊)