AFO

[CH弱省胡策R2]TATT

题目描述
四维空间真是美妙。 现在有nn个四维空间中的点,请求出一条最长的路径,满足任意一维坐标都是单调不降的。 注意路径起点是任意选择的,并且路径与输入顺序无关(路径顺序不一定要满足在输入中是升序)。

路径的长度是经过的点的数量,任意点只能经过一次。


动态插点+替罪羊重构kdtree
刚学kdtree的时候乱写的,丑的要命。有时间重新写一下吧

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstdlib>
#define M 60001
using namespace std;

struct vv
{
	int l,r,d[3],mn[3],mx[3],b,c,s,D;
} t[M];

int a,b,c,n,m,k,D,tmp[M],T,F,C,S,res,RB,cnt,root,ans;

char gc()
{
	static char now[1<<22], *S,*T;
	if(S==T)
	{
		T=(S=now)+fread(now,1,1<<22,stdin);
		if(S==T) return  EOF;
	}
	return *S++;
}

int gi()
{
	int x=0; char c=gc();
	while(c<'0' || c>'9') c=gc();
	while(c>='0' && c<='9') x=x*10+c-'0',c=gc();
	return x;
}

bool cmp(int a,int b)
{
	if(t[a].d[D]!=t[b].d[D]) return t[a].d[D]<t[b].d[D];
	if(t[a].d[(D+1)%3]!=t[b].d[(D+1)%3]) return t[a].d[(D+1)%3]<t[b].d[(D+1)%3];
	return t[a].d[(D+2)%3]<t[b].d[(D+2)%3];
}

bool cmp1(const vv a,const vv b)
{
	if(a.c!=b.c)return a.c<b.c;
	for(int i=0;i<3;i++) if(a.d[i]!=b.d[i]) return a.d[i]<b.d[i];
	return 0;
}

void cs(vv& x)
{
	x.l=x.r=0, x.c=x.b;
	x.s=1;
	for(int i=0;i<3;i++) x.mn[i]=x.mx[i]=x.d[i];
}

void update(vv& x)
{
	x.s=1;
	if(x.l)
	{
		for(int i=0;i<3;i++) x.mn[i]=min(x.mn[i],t[x.l].mn[i]);
		for(int i=0;i<3;i++) x.mx[i]=max(x.mx[i],t[x.l].mx[i]);
		x.c=max(x.c,t[x.l].c);
		x.s+=t[x.l].s;
	}
	if(x.r)
	{
		for(int i=0;i<3;i++) x.mn[i]=min(x.mn[i],t[x.r].mn[i]);
		for(int i=0;i<3;i++) x.mx[i]=max(x.mx[i],t[x.r].mx[i]); 
		x.c=max(x.c,t[x.r].c);
		x.s+=t[x.r].s;
	}
}

int built(int l,int r,int d)
{
	D=rand()%3; int mid=(l+r)>>1;
	
	nth_element(tmp+l,tmp+mid,tmp+r+1,cmp);
	cs(t[tmp[mid]]); t[tmp[mid]].D=D;
	if(mid>l) t[tmp[mid]].l=built(l,mid-1,(d+1)%3);
	if(r>mid) t[tmp[mid]].r=built(mid+1,r,(d+1)%3);
	update(t[tmp[mid]]);
	return tmp[mid];
}

void ask(vv& x) 
{
	if(x.c<=res) return ;
	int b=1,e=1;
	for(int i=0;i<3;i++) 
	{
		if(x.mx[i]>t[T].d[i]) b=0;
		if(x.mn[i]>t[T].d[i]) return ;
		if(x.d[i]>t[T].d[i]) e=0;
	}
	if(b) {res=x.c; return;}
	if(e) res=max(res,x.b);  
	if(x.l) ask(t[x.l]);
	if(x.r) ask(t[x.r]);
}

void ins(int &x,int d)
{
	if(!x) {x=T; return;}
	D=t[x].D;
	if(cmp(T,x)) ins(t[x].l,(d+1)%3);
	else ins(t[x].r,(d+1)%3);
	update(t[x]);
	if((t[t[x].l].s>t[x].s*0.8 || t[t[x].r].s>t[x].s*0.8) && (abs(t[x].s)>=50)) RB=x;//)//  
	if(RB==t[x].l) F=x,C=0;
	if(RB==t[x].r) F=x,C=1;
}

void re(int x)
{
	tmp[++cnt]=x;
	if(t[x].l) re(t[x].l);
	if(t[x].r) re(t[x].r);
}

int main()
{
	//freopen("in.txt","r",stdin);
	srand(time(0));
	n=gi();
	for(int i=1;i<=n;i++) t[i].c=gi(), t[i].d[0]=gi(), t[i].d[1]=gi(), t[i].d[2]=gi();
	sort(t+1,t+1+n,cmp1);
	for(int i=1;i<=n;i++) t[i].c=0;// t[i].D=rand()&1;
	for(int i=1;i<=n;i++)
	{
		T=i; RB=0; cnt=0; F=0;
		res=0; cs(t[i]);
		ask(t[root]);
		ans=max(ans,res+1);
		t[T].b=t[T].c=res+1;
		ins(root,0);
		if(RB) 
		{
			re(RB);
			if(RB==root) root=built(1,cnt,S);
			else if(!C)t[F].l=built(1,cnt,S);
			else t[F].r=built(1,cnt,S);
		}
	}
	printf("%d",ans);
}
posted @ 2019-09-09 15:12  ZUTTER☮  阅读(166)  评论(0编辑  收藏  举报