解题思路
分块码农题,设分成T块,cnt[i][j][k]表示第i块到第j块,k出现的次数,需要离散化。all[i][j] 表示第i块到第j块的众数。然后这两个数组先预处理出来。然后询问的时候先将答案设成区间大块的众数,然后剩余部分暴力往cnt里加来更新答案。T取n^(1/3)时最优,时间复杂度O(n^(5/3))
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int MAXN = 40005;
const int MAXSIZ = 40;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
int n,m,a[MAXN],cnt[MAXSIZ][MAXSIZ][MAXN],now,all[MAXSIZ][MAXSIZ];
int sum[MAXSIZ][MAXSIZ];
int bl[MAXN],l[MAXSIZ],r[MAXSIZ],siz,num,cpy[MAXN],rk[MAXN];
inline int query(int x,int y){
// cout<<bl[x]<<" "<<bl[y]<<endl;
int ret=0,mx=0;
if(bl[x]==bl[y]){
for(register int i=x;i<=y;i++){
int k=rk[i];
cnt[0][0][k]++;
if(cnt[0][0][k]>mx) {mx=cnt[0][0][k];ret=a[i];}
else if(cnt[0][0][k]==mx && a[i]<ret) ret=a[i];
}
for(register int i=x;i<=y;i++){
int k=rk[i];
cnt[0][0][k]--;
}
return ret;
}ret=all[bl[x]+1][bl[y]-1];mx=sum[bl[x]+1][bl[y]-1];
// cout<<ret<<" "<<mx<<endl;
// cout<<r[bl[x]]<<" "<<l[bl[y]]<<endl;
for(register int i=x;i<=r[bl[x]];i++){
int k=rk[i];
cnt[bl[x]+1][bl[y]-1][k]++;
if(cnt[bl[x]+1][bl[y]-1][k]>mx) ret=a[i],mx=cnt[bl[x]+1][bl[y]-1][k];
else if(cnt[bl[x]+1][bl[y]-1][k]==mx && a[i]<ret) ret=a[i];
}
for(register int i=l[bl[y]];i<=y;i++){
int k=rk[i];
cnt[bl[x]+1][bl[y]-1][k]++;
if(cnt[bl[x]+1][bl[y]-1][k]>mx) ret=a[i],mx=cnt[bl[x]+1][bl[y]-1][k];
else if(cnt[bl[x]+1][bl[y]-1][k]==mx && a[i]<ret) ret=a[i];
}
for(register int i=x;i<=r[bl[x]];i++){
int k=rk[i];
cnt[bl[x]+1][bl[y]-1][k]--;
}
for(register int i=l[bl[y]];i<=y;i++){
int k=rk[i];
cnt[bl[x]+1][bl[y]-1][k]--;
}
return ret;
}
int main(){
// freopen("data.txt","r",stdin);
// freopen("A.txt","w",stdout);
n=rd(),m=rd();
for(register int i=1;i<=MAXSIZ;i++)
if(i*i*i>=n) {num=i;break;}
siz=n/num;num++;
for(register int i=1;i<=n;i++) bl[i]=(i-1)/siz+1;
for(register int i=1;i<=num;i++) l[i]=(i-1)*siz+1,r[i]=i*siz;r[num]=n;
for(register int i=1;i<=n;i++) a[i]=rd(),cpy[i]=a[i];sort(cpy+1,cpy+1+n);
now=unique(cpy+1,cpy+1+n)-cpy-1;
for(register int i=1;i<=n;i++) rk[i]=lower_bound(cpy+1,cpy+1+now,a[i])-cpy;
for(register int i=1;i<=num;i++)
for(register int j=i;j<=num;j++)
for(register int k=l[i];k<=r[j];k++){
int p=rk[k];
cnt[i][j][p]++;if(cnt[i][j][p]>sum[i][j]
or (cnt[i][j][p]==sum[i][j] && a[k]<all[i][j]))
sum[i][j]=cnt[i][j][p],all[i][j]=a[k];
}
int pre=0,x,y;
while(m--){
x=rd(),y=rd();x=(x+pre-1)%n+1;y=(y+pre-1)%n+1;
if(x>y) swap(x,y);pre=query(x,y);
// cout<<x<<" "<<y<<endl;
printf("%d
",pre);
}
return 0;
}