SOL
暴力枚舉肯定會T
因此我們需要思考如何快速維護區間衆數
線段樹之類的數據結構複雜度較好,但是在這種情況下不能夠區間合併(區間衆數合併之後不一定還是衆數),而且這道題也沒有修改操作
再看看這個不大不小的數據規模,應該是的算法,於是考慮分塊
分塊雖然也不能支持區間合併,但是我們可以利用分塊特性預處理出每個塊的答案
用一個數組維護每種蒲公英的出現次數
用一個數組維護第塊到第塊的區間衆數及其出現次數
對於一個詢問,我們只用考慮中間完整塊的答案,並暴力統計一下兩邊不完整區間的答案進行比較即可
細節:
注意離散化編號之後要存儲反向映射,因爲輸出要使用原編號
每次暴力統計後數組清空,但不能全部清空,只清空接下來會用到的,否則複雜度會假
代碼:
#include<bits/stdc++.h>
using namespace std;
#define re register
inline int rd(){
int re data=0;static char ch=0;ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))data=(data<<1)+(data<<3)+(ch^48),ch=getchar();
return data;
}
const int N=40005,K=205;
#define mp make_pair
#define cnt first
#define val second
typedef pair<int,int> pii;
int n,m,s[K][N],sec,rev[N],last,tot,rank,num[N];
bool vis[N];
pii p[K][K];
struct node{int v,x,id;}a[N];
inline bool cmp1(node a,node b){if(a.x==b.x)return a.id<b.id;return a.x<b.x;}
inline bool cmp2(node a,node b){return a.id<b.id;}
signed main(){
n=rd(),m=rd();
for(int re i=1;i<=n;++i)a[i].x=rd(),a[i].id=i;
sort(a+1,a+n+1,cmp1);
for(int re i=1;i<=n;++i){
if(a[i].x!=a[i-1].x)rev[++rank]=a[i].x;
a[i].v=rank;
}
sort(a+1,a+n+1,cmp2);
sec=sqrt(n),tot=(n+sec-1)/sec;
for(int re maxl,i=1;i<=tot;++i){
for(int re j=1;j<=n;++j)s[i][a[j].v]=s[i-1][a[j].v];
maxl=min(n,i*sec);
for(int re j=(i-1)*sec+1;j<=maxl;++j)++s[i][a[j].v];
}
for(int re i=1;i<=tot;++i){
memset(num,0,sizeof num);
pii re tmp=mp(0,0);
for(int re maxl,j=i;j<=tot;++j){
maxl=min(n,j*sec);
for(int re k=(j-1)*sec+1;k<=maxl;++k){
++num[a[k].v];
if(num[a[k].v]>tmp.cnt)tmp=mp(num[a[k].v],a[k].v);
else if(num[a[k].v]==tmp.cnt)tmp.val=min(tmp.val,a[k].v);
}p[i][j]=tmp;
}
}memset(num,0,sizeof num);
while(m--){
int re l=rd(),r=rd(),lsec,rsec;
l=(l+last-1)%n+1,r=(r+last-1)%n+1;
if(l>r)swap(l,r);
lsec=(l+sec-1)/sec,rsec=(r+sec-1)/sec;
if(rsec-lsec<=2){
for(int re i=l;i<=r;++i)num[a[i].v]=0;
int re ans=0;
for(int re i=l;i<=r;++i){
++num[a[i].v];
if(num[a[i].v]>num[ans])ans=a[i].v;
else if(num[a[i].v]==num[ans])ans=min(ans,a[i].v);
}printf("%d\n",last=rev[ans]);
}else{
int re maxl=min(n,lsec*sec),ans=p[lsec+1][rsec-1].val;
num[ans]=vis[ans]=0;
for(int re i=l;i<=maxl;++i)num[a[i].v]=vis[a[i].v]=0;
for(int re i=(rsec-1)*sec+1;i<=r;++i)num[a[i].v]=vis[a[i].v]=0;
for(int re i=l;i<=maxl;++i)++num[a[i].v];
for(int re i=(rsec-1)*sec+1;i<=r;++i)++num[a[i].v];
pii re tmp=mp(0,0);
for(int re now,i=l;i<=maxl;++i){
if(vis[a[i].v])continue;vis[a[i].v]=1;
now=num[a[i].v]+s[rsec-1][a[i].v]-s[lsec][a[i].v];
if(now>tmp.cnt)tmp=mp(now,a[i].v);
else if(now==tmp.cnt)tmp.val=min(tmp.val,a[i].v);
}
for(int re now,i=(rsec-1)*sec+1;i<=r;++i){
if(vis[a[i].v])continue;vis[a[i].v]=1;
now=num[a[i].v]+s[rsec-1][a[i].v]-s[lsec][a[i].v];
if(now>tmp.cnt)tmp=mp(now,a[i].v);
else if(now==tmp.cnt)tmp.val=min(tmp.val,a[i].v);
}
if(tmp.cnt>num[ans]+p[lsec+1][rsec-1].cnt)ans=tmp.val;
else if(tmp.cnt==num[ans]+p[lsec+1][rsec-1].cnt)ans=min(tmp.val,ans);
printf("%d\n",last=rev[ans]);
}
}exit(0);
}