BZOJ2724 [Violet]蒲公英(分块)
区间众数。分块,预处理任意两块间所有数的众数,和每块中所有数的出现次数的前缀和。查询时对不是整块的部分暴力,显然只有这里出现的数可能更新答案。于是可以优美地做到O(n√n)。
#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 50010 #define BLOCK 250 int n,m,a[N],b[N],lastans=0; int block,tot,L[N],R[N],pos[N]; int cnt[N],f[BLOCK][BLOCK],sum[BLOCK][N]; int main() { freopen("bzoj2724.in","r",stdin); freopen("bzoj2724.out","w",stdout); n=read(),m=read(); for (int i=1;i<=n;i++) b[i]=a[i]=read(); sort(b+1,b+n+1); int t=unique(b+1,b+n+1)-b; for (int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+t,a[i])-b; 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)); int num=0; for (int j=i;j<=tot;j++) { for (int k=L[j];k<=R[j];k++) { cnt[a[k]]++; if (cnt[a[k]]>cnt[num]||cnt[a[k]]==cnt[num]&&a[k]<num) num=a[k]; } f[i][j]=num; } 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-1)%n+1,y=(y+lastans-1)%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]]>cnt[num]||cnt[a[i]]==cnt[num]&&a[i]<num) num=a[i]; } 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]]>cnt[num]+sum[pos[y]-1][num]-sum[pos[x]][num] ||cnt[a[i]]+sum[pos[y]-1][a[i]]-sum[pos[x]][a[i]]==cnt[num]+sum[pos[y]-1][num]-sum[pos[x]][num]&&a[i]<num) num=a[i]; } 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]]>cnt[num]+sum[pos[y]-1][num]-sum[pos[x]][num] ||cnt[a[i]]+sum[pos[y]-1][a[i]]-sum[pos[x]][a[i]]==cnt[num]+sum[pos[y]-1][num]-sum[pos[x]][num]&&a[i]<num) num=a[i]; } 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=b[num]; printf("%d\n",b[num]); } fclose(stdin);fclose(stdout); return 0; }