BZOJ_2724_[Violet 6]蒲公英_分塊spa
修正一下blog
l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1ip
n <= 40000, m <= 50000string
對於衆數,有一個性質。集合A和集合B的衆數,要麼是集合A的衆數,要麼是集合B中出現過的數。it
根據這個性質咱們考慮分塊。io
先將權值離散化,處理出前綴桶C[i][j]表示1~i塊j數出現的次數。class
在處理出mode[i][j]表示i塊到j塊的衆數,這兩個均可以在O(nsqrt(n))的時間內處理出來。im
查詢時衆數來源有兩個,全部整塊的衆數和零散塊內出現過的數。統計
把零散的每一個數統計一下,用桶能夠O(1)獲得答案。查詢
代碼:
#include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> using namespace std; #define N 40050 struct A { int num,id,v; }a[N]; bool cmp1(const A &x,const A &y){return x.num<y.num;} bool cmp2(const A &x,const A &y){return x.id<y.id;} int n,m,block,pos[N],L[250],R[250],size,mode[250][250],C[250][N],mp[N],times[250][250],ans; int h[N]; void solve(int l,int r) { int p=pos[l],q=pos[r]; int md=0,i; if(p==q||p+1==q) { for(i=l;i<=r;i++) { h[a[i].v]++; if(h[a[i].v]>h[md]||(h[a[i].v]==h[md]&&a[i].v<md)) md=a[i].v; } for(i=l;i<=r;i++) { h[a[i].v]=0; } ans=mp[md]; return ; } int nowmode=mode[p+1][q-1],mtimes=times[p+1][q-1]; h[nowmode]=mtimes; int tmp=nowmode; //printf("nowmode=%d, mtimes=%d\n",nowmode,mtimes); for(i=l;i<=R[p];i++) { if(!h[a[i].v]) { h[a[i].v]=C[q-1][a[i].v]-C[p][a[i].v]; } h[a[i].v]++; //printf("a[i].v=%d h[a[i].v]=%d\n",a[i].v,h[a[i].v]); if(h[a[i].v]>mtimes||(h[a[i].v]==mtimes&&a[i].v<nowmode)) { mtimes=h[a[i].v]; nowmode=a[i].v; } } for(i=L[q];i<=r;i++) { if(!h[a[i].v]) { h[a[i].v]=C[q-1][a[i].v]-C[p][a[i].v]; } h[a[i].v]++; if(h[a[i].v]>mtimes||(h[a[i].v]==mtimes&&a[i].v<nowmode)) { mtimes=h[a[i].v]; nowmode=a[i].v; } } for(i=l;i<=R[p];i++) h[a[i].v]=0; for(i=L[q];i<=r;i++) h[a[i].v]=0; h[tmp]=0; ans=mp[nowmode]; } int main() { scanf("%d%d",&n,&m); int i,j,k,x,y; for(i=1;i<=n;i++) scanf("%d",&a[i].num),a[i].id=i; sort(a+1,a+n+1,cmp1); a[0].num=342344354; for(i=1,j=0;i<=n;i++) { if(a[i].num!=a[i-1].num) j++; a[i].v=j; mp[j]=a[i].num; } sort(a+1,a+n+1,cmp2); size=sqrt(n); block=n/size; for(i=1;i<=block;i++) { L[i]=R[i-1]+1; R[i]=i*size; for(j=L[i];j<=R[i];j++) { pos[j]=i; /*if(!C[i][a[j].v]) { C[i][a[j].v]=C[i-1][a[j].v]; }*/ C[i][a[j].v]++; } for(j=1;j<=R[i];j++) { C[i+1][a[j].v]=C[i][a[j].v]; } } if(R[block]!=n) { block++; L[block]=R[block-1]+1; R[block]=n; for(i=L[block];i<=n;i++) { pos[i]=block; /*if(!C[block][a[i].v]) { C[block][a[i].v]=C[block-1][a[i].v]; }*/ C[block][a[i].v]++; } } for(i=1;i<=block;i++) { int md=0; for(j=L[i];j<=R[i];j++) { if(C[i][a[j].v]-C[i-1][a[j].v]>C[i][md]-C[i-1][md]||(C[i][a[j].v]-C[i-1][a[j].v]==C[i][md]-C[i-1][md]&&a[j].v<md)) md=a[j].v; } mode[i][i]=md; times[i][i]=C[i][md]-C[i-1][md]; for(j=i+1;j<=block;j++) { int md=mode[i][j-1]; for(k=L[j];k<=R[j];k++) { if(C[j][a[k].v]-C[i-1][a[k].v]>C[j][md]-C[i-1][md]||(C[j][a[k].v]-C[i-1][a[k].v]==C[j][md]-C[i-1][md]&&a[k].v<md)) md=a[k].v; } mode[i][j]=md; times[i][j]=C[j][md]-C[i-1][md]; } } //for(i=1;i<=n;i++) printf("i=%d pos[i]=%d\n",i,pos[i]); while(m--) { scanf("%d%d",&x,&y); x=(x+ans-1)%n+1; y=(y+ans-1)%n+1; if(x>y) swap(x,y); solve(x,y); printf("%d\n",ans); } }