BZOJ_2724_[Violet 6]蒲公英_分块
BZOJ_2724_[Violet 6]蒲公英_分块
Description
Input
修正一下
l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1
Output
Sample Input
6 3
1 2 3 2 1 2
1 5
3 6
1 5
1 2 3 2 1 2
1 5
3 6
1 5
Sample Output
1
2
1
2
1
HINT
n <= 40000, m <= 50000
对于众数,有一个性质。集合A和集合B的众数,要么是集合A的众数,要么是集合B中出现过的数。
根据这个性质我们考虑分块。
先将权值离散化,处理出前缀桶C[i][j]表示1~i块j数出现的次数。
在处理出mode[i][j]表示i块到j块的众数,这两个都可以在O(nsqrt(n))的时间内处理出来。
查询时众数来源有两个,所有整块的众数和零散块内出现过的数。
把零散的每个数统计一下,用桶可以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); } }