题意:给N个数,求一个区间内的众数。
思路:分块,分成sqrt(t*log2(n)))块,先预处理出每一个块到每个块中的众数,离散化,然后把询问区间分三段,第一段为l到l所在块的终止,第二段为每一段块,第三段为r块的开始到r,然后第二段用预处理的数组就能得出,第一三段,二分vector记录的下标求众数。
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cstdio>
#include<cmath>
#define ll long long
#define lowbit(x) x&(-x)
using namespace std;
const int N=1e6+10;
int n,t,block;
int a[N],f[N],b[N];
vector<int> g[N];
int c[N],d[1000][1000];
void build()
{
block=max(1,(int)(n/sqrt(t*log2(n))));
for(int i=1;i<=n;i++)
b[i]=(i-1)/block+1;
}
int Count(int l,int r,int val)
{
int t=upper_bound(g[val].begin(),g[val].end(),r)-lower_bound(g[val].begin(),g[val].end(),l);
return t;
}
void pre(int x)
{
memset(c,0,sizeof(c));
int mx=-1,ans=0;
for(int i=(x-1)*block+1;i<=n;i++)
{
c[a[i]]++;
if(c[a[i]]>mx||(c[a[i]]==mx&&a[i]<ans))
{
ans=a[i];
mx=c[a[i]];
}
d[x][b[i]]=ans;//代表x到b[i]块的众数。
}
}
int query(int l,int r)
{
int ans=d[b[l]+1][b[r]-1];
int mx=Count(l,r,ans);
int cnt=0;
int up=min(r,b[l]*block);
for(int i=l;i<=up;i++)
{
cnt=Count(l,r,a[i]);
if(cnt>mx||(cnt==mx&&f[ans]>f[a[i]]))
{
mx=cnt;
ans=a[i];
}
}
if(b[l]!=b[r])
{
for (int i=(b[r]-1)*block+1;i<=r;i++)
{
cnt=Count(l,r,a[i]);
if(cnt>mx||(cnt==mx&&ans>a[i]))
{
mx=cnt;
ans=a[i];
}
}
}
return ans;
}
signed main()
{
scanf("%d%d",&n,&t);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
f[i]=a[i];
}
build();
sort(f+1,f+n+1);
int m=unique(f+1,f+n+1)-f-1;
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(f+1,f+m+1,a[i])-f;
g[a[i]].push_back(i);
}
for(int i=1;i<=b[n];i++)
{
pre(i);
}
int ans=0;
while(t--)
{
int l,r;
scanf("%d%d",&l,&r);
l=(l+ans-1)%n+1;
r=(r+ans-1)%n+1;
if(l>r)
swap(l,r);
ans=f[query(l,r)];
printf("%d\n",ans);
}
}