[bzoj2724]蒲公英
分块,可以发现众数一定是整块的众数或在不整块中出现的数,预处理出f[i][j]表示第i块到第j块的众数,然后对于询问暴力枚举所有散块的数,相当于要支持查询一个数在一个区间内出现的次数,可以用可持久化权值线段树,也可以直接对每一个数开一个vector记录位置二分(离散),时间复杂度是$o(nKlog_{2}n+n^{2}/K)$,取$K=sqrt(n/log_{2}n)$即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define K 205 4 #define N 40005 5 #define bl(k) ((k-1)/K) 6 struct ji{ 7 int id,s; 8 bool operator < (const ji &a)const{ 9 return (s<a.s)||(s==a.s)&&(id>a.id); 10 } 11 }ans,f[K][K]; 12 vector<int>v[N]; 13 int n,m,l,r,a[N],b[N],vis[N]; 14 int query(int k,int l,int r){ 15 return upper_bound(v[k].begin(),v[k].end(),r)-lower_bound(v[k].begin(),v[k].end(),l); 16 } 17 int main(){ 18 scanf("%d%d",&n,&m); 19 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 20 memcpy(b,a,sizeof(b)); 21 sort(b+1,b+n+1); 22 for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+n+1,a[i])-b; 23 for(int i=1;i<=n;i++)v[a[i]].push_back(i); 24 for(int i=0;i<=bl(n);i++){ 25 memset(vis,0,sizeof(vis)); 26 for(int j=i*K+1;j<=n;j++) 27 f[i][bl(j)]=max(f[i][bl(j)],ji{a[j],++vis[a[j]]}); 28 for(int j=i+1;j<=bl(n);j++)f[i][j]=max(f[i][j],f[i][j-1]); 29 } 30 for(int i=1;i<=m;i++){ 31 scanf("%d%d",&l,&r); 32 l=(l+b[ans.id]-1)%n+1; 33 r=(r+b[ans.id]-1)%n+1; 34 if (l>r)swap(l,r); 35 ans=f[bl(l)+1][bl(r)-1]; 36 for(int j=l;j<=min(bl(l)*K+K,r);j++)ans=max(ans,ji{a[j],query(a[j],l,r)}); 37 if (bl(l)!=bl(r)) 38 for(int j=bl(r)*K+1;j<=r;j++)ans=max(ans,ji{a[j],query(a[j],l,r)}); 39 printf("%d\n",b[ans.id]); 40 } 41 }