Description
Input
修正一下
l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1
Output
Sample Input
6 3
1 2 3 2 1 2
1 5
3 6
1 5
1 2 3 2 1 2
1 5
3 6
1 5
Sample Output
1
2
1
2
1
HINT
修正下:
n <= 40000, m <= 50000
Source
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
分块+离散化~
神奇的在线做法~
预处理出块与块之间的答案,然后每次询问的时候在大块的基础上计算边界~
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
#define tot 200
int n,m,a,b,val[50001],v[50001],ans,cnt,poi[50001],kk[50001],f[501][501];
vector<int> ve[50001];
map<int,int> ma;
void pos(int u)
{
memset(kk,0,sizeof(kk));
int maxx=0,num=0;
for(int i=(u-1)*tot+1;i<=n;i++)
{
kk[v[i]]++;
if(kk[v[i]]>maxx || (kk[v[i]]==maxx && val[v[i]]<val[num])) maxx=kk[v[i]],num=v[i];
f[u][poi[i]]=num;
}
}
int findd(int u,int v,int k)
{
return upper_bound(ve[k].begin(),ve[k].end(),v)-lower_bound(ve[k].begin(),ve[k].end(),u);
}
int cal(int a,int b)
{
int ans=f[poi[a]+1][poi[b]-1],maxx=findd(a,b,ans);
for(int i=a;i<=min(b,poi[a]*tot);i++)
{
int now=findd(a,b,v[i]);
if(now>maxx || (now==maxx && val[v[i]]<val[ans])) maxx=now,ans=v[i];
}
if(poi[a]!=poi[b])
for(int i=(poi[b]-1)*tot+1;i<=b;i++)
{
int now=findd(a,b,v[i]);
if(now>maxx || (now==maxx && val[v[i]]<val[ans])) maxx=now,ans=v[i];
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&v[i]);
if(!ma[v[i]])
{
ma[v[i]]=++cnt;
val[cnt]=v[i];
}
v[i]=ma[v[i]];
ve[v[i]].push_back(i);
}
for(int i=1;i<=n;i++) poi[i]=(i-1)/tot+1;
for(int i=1;i<=poi[n];i++) pos(i);
while(m--)
{
scanf("%d%d",&a,&b);
a=(ans+a-1)%n+1;b=(ans+b-1)%n+1;
if(a>b) swap(a,b);ans=val[cal(a,b)];
printf("%d\n",ans);
}
return 0;
}