【BZOJ 2714】蒲公英
https://blog.csdn.net/nixinyis/article/details/68075234?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1
给一个序列,求一个区间的众数。(强制在线)
Sol:
先分块。
设f[i][j]表示第i块到第j块总的众数。
然后每次对于一个询问[l,r],x到y已经知晓,
答案只可能是l~x,y~r,和块x~y的众数之一,
所以接下来要做的就是判断l~x和y~r中存不存在数字出现次数比块x到y众数出现更多的数。
不过怎么判断呢?可以先用vector来保存每个数字出现的位置
(因为本题的值域较大,所以要离散化一下,就是map来搞一搞),
在用二分答案查找这个数字在[l,r]内出现的次数即可
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<map> #define N 40010 #define B 200 using namespace std; map<int,int> mp; vector<int> pos[N]; int cnt,val[N],a[N]; int belong[N],tot[N],f[B+5][B+5]; int n; void pre(int x) { int now = 0,maxnsum = 0; memset(tot,0,sizeof(tot)); for(int i = (x-1)*B + 1;i <= n;i++) { tot[a[i]] ++; if(tot[a[i]] > maxnsum || (tot[a[i]] == maxnsum && val[now] > val[a[i]]) ) now = a[i],maxnsum = tot[a[i]]; f[x][belong[i]] = now; //f[i][j]表示第i块到第j块总的众数 } } int sigma(int l,int r,int x) { return upper_bound(pos[x].begin(),pos[x].end(),r)-lower_bound(pos[x].begin(),pos[x].end(),l); } int query(int l,int r) { int now = f[belong[l]+1][belong[r]-1],maxnsum = sigma(l,r,now); for(int i = l;i <= min(r,belong[l]*B);i++) //左边区间 [l,min(r,belong[l]*B) { int tmp = sigma(l,r,a[i]); if(tmp > maxnsum || (tmp == maxnsum && val[now] > val[a[i]]) ) now = a[i],maxnsum = tmp; } if(belong[l] != belong[r]) { for(int i = (belong[r]-1)*B+1;i <= r;i++) //左边区间 [(belong[r]-1)*B+1,r] { int tmp = sigma(l,r,a[i]); if(tmp > maxnsum || (tmp == maxnsum && val[now] > val[a[i]]) ) now = a[i],maxnsum = tmp; } } return now; } int main() { int m,l,r; int ans = cnt = 0; scanf("%d%d",&n,&m); for(int i = 1;i <= n;i++) { scanf("%d",&a[i]); if(!mp[a[i]]) { mp[a[i]] = ++cnt; val[cnt] = a[i]; } a[i] = mp[a[i]]; pos[a[i]].push_back(i); } for(int i = 1;i <= n;i++) belong[i] = (i-1)/B + 1; for(int i = 1;i <= belong[n];i++) pre(i); for(int i = 1;i <= m;i++) { scanf("%d%d",&l,&r); l = (l+ans-1) % n + 1; r = (r+ans-1) % n + 1; if(l > r) swap(l,r); ans = val[query(l,r)]; printf("%d\n",ans); } return 0; }