[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);
}