[KD-tree] Luogu P3769 TATT

题目描述

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

题解

  • 第一维排序,然后就是个3D-tree

代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #define N 50010
 6 using namespace std;
 7 int n,ans,Ans,D,root,fa[N],pos[N],p[3][4];
 8 struct node 
 9 { 
10     int d[4],id;
11     bool operator < (const node &a) const { return d[D]<a.d[D]; }
12 }a[N];
13 struct kdtree{int d[3],mn[3],mx[3],ch[2],v,q;}t[N];
14 bool cmp(node a,node b) { for (int k=3;~k;k--) if (a.d[k]^b.d[k]) return a.d[k]<b.d[k]; return a.id<b.id; }
15 void change(int x,int y) { for (int i=0;i<3;i++) t[x].mn[i]=min(t[x].mn[i],t[y].mn[i]),t[x].mx[i]=max(t[x].mx[i],t[y].mx[i]); }
16 bool pd1(int x) { for (int i=0;i<3;i++) if (t[x].mn[i]<p[0][i]||t[x].mx[i]>p[1][i]) return false; return true; }
17 bool pd2(int x) { for (int i=0;i<3;i++) if (t[x].mn[i]>p[1][i]||t[x].mx[i]<p[0][i]) return true; return false; }
18 bool pd3(int x) { for (int i=0;i<3;i++) if (t[x].d[i]<p[0][i]||t[x].d[i]>p[1][i]) return false; return true; }
19 int build(int d,int l,int r)
20 {
21     int mid=l+r>>1;
22     D=d,nth_element(a+l,a+mid,a+r+1),pos[a[mid].id]=mid;
23     for (int i=0;i<3;i++) t[mid].d[i]=t[mid].mn[i]=t[mid].mx[i]=a[mid].d[i];
24     if (l<mid) fa[t[mid].ch[0]=build((d+1)%3,l,mid-1)]=mid,change(mid,t[mid].ch[0]);
25     if (r>mid) fa[t[mid].ch[1]=build((d+1)%3,mid+1,r)]=mid,change(mid,t[mid].ch[1]);
26     return mid;
27 }
28 void query(int d)
29 {
30     if (t[d].q<=ans) return;
31     if (pd1(d)) { ans=max(ans,t[d].q); return; }
32     if (pd2(d)) return;
33     if (pd3(d)) ans=max(ans,t[d].v);
34     if (t[d].ch[0]) query(t[d].ch[0]);
35     if (t[d].ch[1]) query(t[d].ch[1]);
36 }
37 int main()
38 {    
39     scanf("%d",&n);
40     for (int i=1;i<=n;i++) { for (int j=0;j<4;j++) scanf("%d",&a[i].d[j]); a[i].id=i; }
41     root=build(0,1,n),sort(a+1,a+n+1,cmp);
42     for (int i=1;i<=n;i++)
43     {
44         for (int j=0;j<3;j++) p[0][j]=0,p[1][j]=a[i].d[j];
45         ans=0,query(root),ans++,Ans=max(Ans,ans),t[pos[a[i].id]].v=ans;
46         for (int p=pos[a[i].id];p;p=fa[p]) t[p].q=max(t[p].q,ans);
47     }
48     printf("%d",Ans);
49 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/11312901.html