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
",ans);
}
return 0;
}