【bzoj 3489】A simple rmq problem(KD-Tree模板)

傳送門~
作爲簡易的KdK-d treetree模板
將一個數作爲一個點(x,y,z)(x,y,z)
xx爲該點位置,yy爲左面第一個和它一樣的數的位置,zz是右面第一個和他一樣的數的位置
問題轉化成,給定llrr,求一個權值最大的點,使
y<ly<l
z>rz>r
r=>x=>lr=>x=>l
就成了在一個長方體中求一個最大的值
代碼:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<cstdlib>
using namespace std;
int num[200005],point[200005];
int pre[200005],nex[200005];
int cmpd,n,m,ans,lx,ly,root;
struct data{
	int d[3],mx[3],mn[3],val,maxn;
	int l,r;
}s[200005];
bool cmp(data r1,data r2){
	return r1.d[cmpd]<r2.d[cmpd];
}
void maintain(int now){
	int l=s[now].l,r=s[now].r;  
    for (int i=0;i<=2;i++){  
        if(l){s[now].mx[i]=max(s[now].mx[i],s[l].mx[i]);s[now].mn[i]=min(s[now].mn[i],s[l].mn[i]);}
        if(r){s[now].mx[i]=max(s[now].mx[i],s[r].mx[i]);s[now].mn[i]=min(s[now].mn[i],s[r].mn[i]);}        
    }  
    if(l) s[now].maxn=max(s[l].maxn,s[now].maxn);
    if(r) s[now].maxn=max(s[r].maxn,s[now].maxn);
}

int build(int l,int r,int d){
	if(l>r) return 0;
	d%=3;cmpd=d;
	int mid=l+r>>1;
	nth_element(s+l,s+mid,s+r+1,cmp);
	for(int i=0;i<=2;i++) s[mid].mx[i]=s[mid].mn[i]=s[mid].d[i];
	s[mid].l=build(l,mid-1,d+1);
	s[mid].r=build(mid+1,r,d+1);
	maintain(mid);
	return mid;
}
bool check(int now){
	if(s[now].mx[0]<lx || s[now].mn[0]>ly) return 0;
	if(s[now].mn[1]>=lx) return 0;
	if(s[now].mx[2]<=ly) return 0;	
	return 1;
}
void ch(int now){
	if(s[now].d[0]>=lx && s[now].d[0]<=ly && s[now].d[1]<lx && s[now].d[2]>ly) ans=max(ans,s[now].val);
	int l=s[now].l,r=s[now].r;
	if(l && s[l].maxn>ans && check(l)) ch(l);
	if(r && s[r].maxn>ans && check(r)) ch(r);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&num[i]);
	for(int i=1;i<=n;i++) {pre[i]=point[num[i]];point[num[i]]=i;}
	for(int i=1;i<=n;i++) point[i]=n+1;
	for(int i=n;i>=1;i--) {nex[i]=point[num[i]];point[num[i]]=i;}
	for(int i=1;i<=n;i++) {s[i].d[0]=i;s[i].d[1]=pre[i];s[i].d[2]=nex[i];s[i].val=num[i];s[i].maxn=num[i];}
	root=build(1,n,0);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&lx,&ly);
		lx=(lx+ans)%n+1;
		ly=(ly+ans)%n+1;
		if(lx>ly) swap(lx,ly);
		ans=0;ch(root);
		printf("%d\n",ans);	
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章