______l______ @ 2022-09-25 15:12:00
按第一篇题解的思路去写的 具体思路在代码注释里 除了18其它全WA
#include<bits/stdc++.h>
//#pragma GCC optimize(3,"Ofast","inline")
//#define int long long
using namespace std;
const int N=1e5+10,sqrtN=sqrt(N);int n,m,q;
int a[N],x[N],ans[sqrtN][sqrtN],s[sqrtN][N],p[N];
int l[sqrtN],r[sqrtN],t,num;
/*
ans[i][j]:块i~块j的众数
s[i][j]:前i块中x[j]出现的次数(j是离散化编号)
*/
inline int time10(int x)
{return(x<<3)+(x<<1);}
inline int read(){//快读
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
if(ch==-1)exit(0);
ch=getchar();
}
while(ch>='0'&&ch<='9')
x=time10(x)+(ch^48),ch=getchar();
return x*f;
}
inline void write(int x){//快写
if(x<0)putchar('-'),x=-x;
if(x<10){putchar(x+48);return;}
write(x/10);putchar(x%10+48);
}
inline int name(int k){//查k的离散化编号
return lower_bound(x+1,x+m+1,k)-x;
}
inline void init(int k){//分块
p[k]=k/t+1;//块的编号
if(p[k]!=p[k-1])//和上一个数不是同一个块
r[p[k-1]]=k-1,l[p[k]]=k;//这两个数是块的边界
if(k==n)r[p[k]]=k;//最后一个数
}int cnt[N],cut[N];
inline int ask(int ql,int qr,int x){//查询块ql~块qr中x出现的次数
int k=name(x);
return s[qr][k]-s[ql-1][k];
}//前缀和
inline int query(int ql,int qr){//询问O(sqrt n)
memset(cnt,0,sizeof cnt);//清零
if(p[qr]-p[ql]<=1){//中间没有完整块
int as=INT_MAX,ar=0;//记录
for(int i=ql;i<=qr;i++){//暴力求答案
int k=name(a[i]);
cnt[k]++;
if(cnt[k]>ar||(cnt[k]==ar&&a[i]<as))
ar=cnt[k],as=a[i];
}return as;
}if(l[p[ql]]==ql&&r[p[qr]]==qr)//边界的两数
return ans[p[ql]][p[qr]];
int ans1=ans[p[ql]+1][p[qr]-1];
int cnt1=ask(p[ql]+1,p[qr]-1,ans1);
//答案1:中间整块的众数
int ans2=INT_MAX,cnt2=0;
//答案2:整块边的数+这个数在中间整块中出现次数
for(int i=ql;i<=r[p[ql]];i++){//ql所在块
int k=name(a[i]);cnt[k]++;
if(cnt[k]==1)//第一次记录
cnt[k]+=ask(p[ql]+1,p[qr]-1,a[i]);//将中间的也加上
if(cnt[k]>cnt2||(cnt[k]==cnt2&&a[i]<ans2))//赋值
cnt2=cnt[k],ans2=a[i];
}
for(int i=l[p[qr]];i<=qr;i++){//qr所在块
int k=name(a[i]);cnt[k]++;//同上
if(cnt[k]==1)
cnt[k]+=ask(p[ql]+1,p[qr]-1,a[i]);
if(cnt[k]>cnt2||(cnt[k]==cnt2&&a[i]<ans2))
cnt2=cnt[k],ans2=a[i];
}//cout<<ans1<<":"<<cnt1<<"/"<<ans2<<":"<<cnt2<<"——";
return(cnt1>cnt2||(cnt1==cnt2&&ans1<ans2))?ans1:ans2;//选择答案
}
signed main(){
n=read(),q=read();t=sqrt(n);num=n/t+1;
for(int i=1;i<=n;i++)//输入
a[i]=read(),x[i]=a[i],init(i);
sort(x+1,x+n+1);
m=unique(x+1,x+n+1)-x;
/*离散化*/
int ks=INT_MAX,kr=0;
/*O(n)*/
for(int i=1;i<=num;i++)//枚举整块
for(int j=l[i];j<=r[i];j++){//预处理s数组
int xh=name(a[j]);
cnt[xh]++;
if(cnt[xh]>kr||(cnt[xh]==kr&&a[j]<ks))
kr=cnt[xh],ks=a[j];//无视就好
s[i][xh]=cnt[xh];
}
int ts=INT_MAX,tr=0;
/*O(n sqrt n)*/
for(int i=1;i<=num;i++){//枚举<起点>
memset(cut,0,sizeof cut);//归零
ts=INT_MAX,tr=0;//记录答案
for(int j=i;j<=num;j++){//枚举块&自己
for(int k=l[j];k<=r[j];k++){//
int xh=name(a[k]);
cut[xh]++;
if(cut[xh]>tr||(cut[xh]==tr&&a[k]<ts))
tr=cut[xh],ts=a[k];
}ans[i][j]=ts;//保存答案
// cout<<"第"<<l[i]<<"到第"<<r[j]<<":"<<ans[i][j]<<"\n";
}
}int answer=0;//上一次询问答案
while(q--){
int sl=read(),sr=read();
int ql=((sl+answer-1)%n)+1;
int qr=((sr+answer-1)%n)+1;
// cout<<ql<<"~"<<qr<<":";
if(ql>qr)swap(ql,qr);
write(answer=query(ql,qr)),
putchar('\n');//输出
}fclose(stdin);
fclose(stdout);
return 0;
}
蒟蒻求助!!!