BZOJ 3489 A simple rmq problem ——KD-Tree

考前写写板子。

用$(i,pre[i],nxt[i])$来描述一个点,然后就变成了区间求最值的问题。

KD-Tree 由低维转向高维的方法,可以用来敲暴力。

剩下就是KD-Tree的基本操作了。

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define inf 0x3f3f3f3f
#define L t[o].ch[0]
#define R t[o].ch[1]
#define ll long long
#define mp make_pair
#define maxn 200005

int D,a[maxn],n,m,ans,pre[maxn],nxt[maxn],lst[maxn],rt;
int ql,qr;
struct Point{
	int d[3],mn[3],mx[3],ch[2],v,vmax;
}t[maxn];//i pre nxt

bool operator < (Point a,Point b){return a.d[D]<b.d[D];}

void pushup(int o)
{
	F(i,0,2) t[o].mx[i]=t[o].mn[i]=t[o].d[i];
	F(i,0,2)
	{
		t[o].mx[i]=max(max(t[L].mx[i],t[R].mx[i]),t[o].mx[i]);
		t[o].mn[i]=min(min(t[L].mn[i],t[R].mn[i]),t[o].mn[i]);
	}
	t[o].vmax=max(t[o].v,max(t[L].vmax,t[R].vmax));
}

void init(){F(i,0,2) t[0].mn[i]=inf,t[0].mx[i]=-inf;}

int build(int l,int r,int dir)
{
	D=dir;int mid=l+r>>1;int o=mid;
	nth_element(t+l,t+mid,t+r+1);
	L=l<mid?build(l,mid-1,(dir+1)%3):0;
	R=r>mid?build(mid+1,r,(dir+1)%3):0;
	pushup(o); return o;
}

bool in(int o)
{
	if (t[o].mx[1]>=ql||t[o].mn[2]<=qr) return 0;
	if (t[o].mx[0]>qr||t[o].mx[1]<ql) return 0;
	return 1;
}

bool pin(int o)
{
	if (t[o].d[0]>=ql&&t[o].d[0]<=qr&&t[o].d[1]<ql&&t[o].d[2]>qr) return 1;
	return 0;
}

bool check(int o)
{
	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 (!o) return;
	if (in(o)) {ans=max(ans,t[o].vmax);return;}
	if (pin(o)) ans=max(ans,t[o].v);
	if (t[L].vmax>t[R].vmax)
	{
		if (t[L].vmax>ans&&check(L)) query(L);
		if (t[R].vmax>ans&&check(R)) query(R);
	}
	else
	{
		if (t[R].vmax>ans&&check(R)) query(R);
		if (t[L].vmax>ans&&check(L)) query(L);
	}
}

int main()
{
	scanf("%d%d",&n,&m);init();
	F(i,1,n) scanf("%d",&a[i]);
	F(i,1,n) lst[i]=0;
	F(i,1,n) pre[i]=lst[a[i]],lst[a[i]]=i;
	F(i,1,n) lst[i]=n+1;
	D(i,n,1) nxt[i]=lst[a[i]],lst[a[i]]=i;
	F(i,1,n) t[i].d[0]=i,t[i].d[1]=pre[i],t[i].d[2]=nxt[i],t[i].v=a[i];
	rt=build(1,n,0);
	F(i,1,m)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		ql=min((x+ans)%n+1,(y+ans)%n+1);
		qr=max((x+ans)%n+1,(y+ans)%n+1);
		ans=0;query(rt);printf("%d\n",ans);
	}
	return 0;
}

  

posted @ 2017-04-21 10:00  SfailSth  阅读(319)  评论(0编辑  收藏  举报