1. 程式人生 > >bzoj2724 [Violet 6]蒲公英 分塊

bzoj2724 [Violet 6]蒲公英 分塊

題意:強制線上,求區間眾數。
說實話還沒有用過除了反演莫隊以外的分塊。。
具體的話就是分成sqrtn塊,然後記錄每一塊的答案和字首。
然後詢問的時候,如果

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=2e5+5
; typedef long long ll; const int mx=305; int ans[mx][mx],n,m,l,r; int sum[N][mx],cnt[N]; int a[N],b[N],bel[N]; int main() { scanf("%d%d",&n,&m); int c=floor(sqrt(n))+1; fo(i,1,n) { scanf("%d",&a[i]); bel[i]=(i-1)/c+1; b[i]=a[i]; } sort(b+1,b+1
+n); l=unique(b+1,b+n+1)-b-1; fo(i,1,n) a[i]=lower_bound(b+1,b+l+1,a[i])-b; fo(i,1,bel[n]) { int x=0; fo(j,(i-1)*c+1,n) { cnt[a[j]]++; if(!x||cnt[a[j]]>cnt[x]||cnt[a[j]]==cnt[x]&&a[j]<x)x=a[j]; ans[i][bel[j]]=x; } fo(j,(i-1
)*c+1,n) if (cnt[a[j]])cnt[a[j]]=0; } fo(i,1,n)sum[a[i]][bel[i]]++; fo(i,1,l) fo(j,1,bel[n]) sum[i][j]+=sum[i][j-1]; int x=0; while (m--) { int u,v; scanf("%d%d",&u,&v); u=1ll*(u+x-1)%n+1; v=1ll*(v+x-1)%n+1; if (u>v)swap(u,v); int l=bel[u],r=bel[v]; if (r-l<=1) { x=0; fo(i,u,v) { cnt[a[i]]++; if (!x||cnt[a[i]]>cnt[x]||cnt[a[i]]==cnt[x]&&a[i]<x)x=a[i]; } fo(i,u,v)if (cnt[a[i]])cnt[a[i]]=0; x=b[x]; printf("%d\n",x); continue; } x=ans[l+1][r-1]; fo(i,u,l*c) { cnt[a[i]]++; if (!x||cnt[a[i]]+sum[a[i]][r-1]-sum[a[i]][l]>cnt[x]+sum[x][r-1]-sum[x][l]||cnt[a[i]]+sum[a[i]][r-1]-sum[a[i]][l]==cnt[x]+sum[x][r-1]-sum[x][l]&&a[i]<x) x=a[i]; } fo(i,(r-1)*c+1,v) { cnt[a[i]]++; if (!x||cnt[a[i]]+sum[a[i]][r-1]-sum[a[i]][l]>cnt[x]+sum[x][r-1]-sum[x][l]||cnt[a[i]]+sum[a[i]][r-1]-sum[a[i]][l]==cnt[x]+sum[x][r-1]-sum[x][l]&&a[i]<x) x=a[i]; } fo(i,u,l*c) if (cnt[a[i]])cnt[a[i]]=0; fo(i,(r-1)*c+1,v) if (cnt[a[i]])cnt[a[i]]=0; x=b[x]; printf("%d\n",x); } }