题目传送门
题目分析:
记下每个数的 前一次出现位置
p
r
e
pre
pre 和 后一次出现位置
n
x
t
nxt
nxt
于是每个点就变成一个三维的点
(
p
o
s
i
,
p
r
e
i
,
n
x
t
i
)
(pos_i,pre_i,nxt_i)
(posi,prei,nxti)
那么查询
[
l
,
r
]
[l,r]
[l,r]只出现一次数的最大值
就相当于查询
p
o
s
∈
[
l
,
r
]
,
p
r
e
∈
[
0
,
l
−
1
]
,
n
x
t
∈
[
r
+
1
,
n
+
1
]
pos\in[l,r],pre\in[0,l-1],nxt\in[r+1,n+1]
pos∈[l,r],pre∈[0,l−1],nxt∈[r+1,n+1]的点的最大值
裸裸的三维KD树就OK了(什么二维线段树不存在的 )
Code(10188 ms):
#include<cstdio>
#include<cctype>
#include<algorithm>
#define maxn 100005
#define lc t[o].ch[0]
#define rc t[o].ch[1]
using namespace std;
inline void read(int &a){
char c;while(!isdigit(c=getchar()));
for(a=c-'0';isdigit(c=getchar());a=a*10+c-'0');
}
int n,m,D,root,v[maxn],pos[maxn];
int ql,qr,ans;
struct KD_tree{
int d[3],mn[3],mx[3],ch[2],v,s;
bool operator < (const KD_tree &t)const{return d[D]<t.d[D];}
}t[maxn];
inline void cmin(int &a,int b){if(a>b) a=b;}
inline void cmax(int &a,int b){if(a<b) a=b;}
inline void mt(int o,int x){
t[o].s=max(t[o].s,t[x].s);
for(int i=0;i<3;i++) cmin(t[o].mn[i],t[x].mn[i]),cmax(t[o].mx[i],t[x].mx[i]);
}
inline void mt(int o){if(lc) mt(o,lc); if(rc) mt(o,rc);}
int build(int l,int r,int nd){
int o=(l+r)>>1;D=nd;
nth_element(t+l,t+o,t+r+1);
t[o].s=t[o].v;
for(int i=0;i<3;i++) t[o].mn[i]=t[o].mx[i]=t[o].d[i];
if(l<o) lc=build(l,o-1,(nd+1)%3); else lc=0;
if(r>o) rc=build(o+1,r,(nd+1)%3); else rc=0;
mt(o);return o;
}
inline bool check(int o){
if(!o) return 0;
if(t[o].mx[0]<ql||t[o].mn[0]>qr) return 0;
if(t[o].mn[1]>=ql||t[o].mx[2]<=qr) return 0;
return 1;
}
void query(int o)
{
if(ql<=t[o].mn[0]&&t[o].mx[0]<=qr&&t[o].mx[1]<ql&&t[o].mn[2]>qr) {ans=max(ans,t[o].s);return;}
if(ql<=t[o].d[0]&&t[o].d[0]<=qr&&t[o].d[1]<ql&&t[o].d[2]>qr) ans=max(ans,t[o].v);
int w[2]={t[lc].s,t[rc].s},tmp=w[1]>=w[0];
if(ans<w[tmp]&&check(t[o].ch[tmp])) query(t[o].ch[tmp]);tmp^=1;
if(ans<w[tmp]&&check(t[o].ch[tmp])) query(t[o].ch[tmp]);
}
int main()
{
read(n),read(m);
for(int i=1;i<=n;i++){
read(v[i]);
t[i].v=v[i];
t[i].d[0]=i,t[i].d[1]=pos[v[i]];
t[i].d[2]=n+1,t[pos[v[i]]].d[2]=i;
pos[v[i]]=i;
}
root=build(1,n,0);
int x,y,l,r;
while(m--){
read(x),read(y);
l=min((x+ans)%n+1,(y+ans)%n+1);
r=max((x+ans)%n+1,(y+ans)%n+1);
ql=l,qr=r,ans=0;query(root);
printf("%d\n",ans);
}
}