[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 }
View Code

猜你喜欢

转载自www.cnblogs.com/PYWBKTDA/p/11371424.html