在[l,r]内找只出现一次的,最大的数
用pre记录每个位置的数上次出现位置,nex记录下次出现位置
一个位置i的值在[l,r]内只出现一次,那么 l <= i <= r , prei< l, nexi>r,所以给一个点三维坐标(i,prei,nexi),询问时用kd-tree找(l~r,0~l-1,r+1~n+1)里最大的值
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int read()
{
char c; int x;
while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
return x;
}
void up(int &x,const int y){if(x<y)x=y;}
void down(int &x,const int y){if(x>y)x=y;}
const int maxn = 110000;
const int maxd = 3;
struct Kd_tree
{
int s,c,pos[maxd],u[maxd],d[maxd],lc,rc;
}kd[maxn]; int root;
int n,m;
int cmp_d;
bool cmp(const Kd_tree &x,const Kd_tree &y) { return x.pos[cmp_d]<y.pos[cmp_d]; }
void push_up(const int &x)
{
const int lc=kd[x].lc,rc=kd[x].rc;
if(lc)
{
for(int i=0;i<maxd;i++)
up(kd[x].u[i],kd[lc].u[i]),
down(kd[x].d[i],kd[lc].d[i]);
up(kd[x].c,kd[lc].c);
}
if(rc)
{
for(int i=0;i<maxd;i++)
up(kd[x].u[i],kd[rc].u[i]),
down(kd[x].d[i],kd[rc].d[i]);
up(kd[x].c,kd[rc].c);
}
}
int Build(int l,int r,int D)
{
cmp_d=D; int mid=(l+r)>>1;
std::nth_element(kd+l,kd+mid,kd+r+1,cmp);
for(int i=0;i<maxd;i++)
kd[mid].u[i]=kd[mid].d[i]=kd[mid].pos[i];
kd[mid].c=kd[mid].s; kd[mid].lc=kd[mid].rc=0;
if(l==r) return mid;
if(l!=mid) kd[mid].lc=Build(l,mid-1,(D+1)%3);
if(mid!=r) kd[mid].rc=Build(mid+1,r,(D+1)%3);
push_up(mid);
return mid;
}
int Pu[maxd],Pd[maxn];
int Cal(const int x)
{
if(!x) return 0;
for(int i=0;i<maxd;i++)
if(kd[x].d[i]>Pu[i]||kd[x].u[i]<Pd[i]) return 0;
return kd[x].c;
}
int Ask(const int x)
{
for(int i=0;i<maxd;i++)
if(kd[x].d[i]>Pu[i]||kd[x].u[i]<Pd[i]) return 0;
bool flag=true;
for(int i=0;i<maxd;i++)
if(!(Pd[i]<=kd[x].d[i]&&kd[x].u[i]<=Pu[i])) {flag=false; break;}
if(flag) return kd[x].c;
int re=0;
flag=true;
for(int i=0;i<maxd;i++)
if(!(Pd[i]<=kd[x].pos[i]&&kd[x].pos[i]<=Pu[i])) {flag=false; break;}
if(flag) re=kd[x].s;
int k1=Cal(kd[x].lc),k2=Cal(kd[x].rc);
if(k1>k2)
{
if(k1>re) up(re,Ask(kd[x].lc));
if(k2>re) up(re,Ask(kd[x].rc));
}
else
{
if(k2>re) up(re,Ask(kd[x].rc));
if(k1>re) up(re,Ask(kd[x].lc));
}
return re;
}
int Posi[maxn];
int a[maxn],pre[maxn],nex[maxn];
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++)
pre[i]=Posi[a[i]],Posi[a[i]]=i;
for(int i=1;i<=n;i++) Posi[i]=n+1;
for(int i=n;i>=1;i--)
nex[i]=Posi[a[i]],Posi[a[i]]=i;
for(int i=1;i<=n;i++)
kd[i].s=a[i],kd[i].pos[0]=i,kd[i].pos[1]=pre[i],kd[i].pos[2]=nex[i];
Build(1,n,0); root=(1+n)>>1;
int ans=0;
while(m--)
{
int x=(read()+ans)%n+1,y=(read()+ans)%n+1;
int l=min(x,y),r=max(x,y);
Pd[0]=l,Pu[0]=r;
Pd[1]=0,Pu[1]=l-1;
Pd[2]=r+1,Pu[2]=n+1;
printf("%d\n",ans=Ask(root));
}
return 0;
}