K-D树解决一些传统的序列问题,详细解法可参见任之洲《k-d tree在传统OI数据结构题中的应用》
用
lastx
表示
x
上次出现的位置,
复杂度
O(mn23)
#include<iostream>
#include<cstdio>
#include<algorithm>
#define inf 1000000007
#define N 100005
using namespace std;
struct node
{
int d[3],mn[3],mx[3];
int v,mv;
};
node tree[N];
int ls[N],rs[N],pre[N];
int n,m,ans,root,L,R,D;
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline bool operator<(node a,node b)
{
return a.d[D]<b.d[D];
}
inline void pushup(int k)
{
for (int i=0;i<=2;i++)
{
tree[k].mn[i]=min(tree[k].d[i],min(tree[ls[k]].mn[i],tree[rs[k]].mn[i]));
tree[k].mx[i]=max(tree[k].d[i],max(tree[ls[k]].mx[i],tree[rs[k]].mx[i]));
}
tree[k].mv=max(tree[k].v,max(tree[ls[k]].mv,tree[rs[k]].mv));
}
void build(int &k,int l,int r,int dir)
{
int mid=l+r>>1; k=mid; D=dir;
nth_element(tree+l,tree+mid,tree+r+1);
if (l<mid) build(ls[k],l,mid-1,(dir+1)%3);
if (r>mid) build(rs[k],mid+1,r,(dir+1)%3);
pushup(k);
}
inline bool check(int k)
{
if (!k) return 0;
if (tree[k].mn[1]>=L||tree[k].mx[2]<=R||tree[k].mx[0]<L||tree[k].mn[0]>R) return 0;
return 1;
}
void query(int k)
{
if (!k) return;
if (tree[k].mn[0]>=L&&tree[k].mx[0]<=R&&tree[k].mx[1]<L&&tree[k].mn[2]>R)
{
ans=max(ans,tree[k].mv);
return;
}
if (tree[k].d[0]>=L&&tree[k].d[0]<=R&&tree[k].d[1]<L&&tree[k].d[2]>R)
ans=max(ans,tree[k].v);
if (tree[ls[k]].mv>tree[rs[k]].mv)
{
if (tree[ls[k]].mv>ans&&check(ls[k])) query(ls[k]);
if (tree[rs[k]].mv>ans&&check(rs[k])) query(rs[k]);
}
else
{
if (tree[rs[k]].mv>ans&&check(rs[k])) query(rs[k]);
if (tree[ls[k]].mv>ans&&check(ls[k])) query(ls[k]);
}
}
int main()
{
for (int i=0;i<=2;i++)
tree[0].mx[i]=-inf,tree[0].mn[i]=inf;
n=read(); m=read();
for (int i=1;i<=n;i++)
{
int x=read();
tree[i].d[0]=i; tree[i].d[2]=n+1; tree[i].v=tree[i].mv=x;
if (pre[x]) tree[i].d[1]=pre[x],tree[pre[x]].d[2]=i;
pre[x]=i;
}
build(root,1,n,0);
for (int i=1;i<=m;i++)
{
int x=read(),y=read();
L=min((x+ans)%n+1,(y+ans)%n+1);
R=max((x+ans)%n+1,(y+ans)%n+1);
ans=0;
query(root);
printf("%d\n",ans);
}
return 0;
}