k-d tree 写法 RE 求调
查看原帖
k-d tree 写法 RE 求调
305891
Eraine楼主2024/6/12 17:09

rt,按照题解区奆佬的做法,将静态四维偏序转为动态三维偏序,再用 k-d tree 优化 dp,时间复杂度 Θ(n53)\Theta(n^{\frac{5}{3}})。

RE on #2。

代码应该还算清晰,就不写注释了。

#include<bits/stdc++.h>
using namespace std;
const int N=5e4+5;
const int inf=1e9;
int cmptype=-1;
struct Point{
    int id,x0;
    vector<int>x;
    friend bool operator<(Point A,Point B){
        if(~cmptype){
            return A.x[cmptype]<B.x[cmptype];
        }
        if(A.x0!=B.x0){
            return A.x0<B.x0;
        }
        for(int i=0;i<3;i++){
            if(A.x[i]!=B.x[i]){
                return A.x[i]<B.x[i];
            }
        }
        return 1;
    }
}a[N];
int p[N],p2[N],idx;
struct node{
    int ch[2];
    int par;
    vector<int>l,r,x;
    int val,maxn;
}tr[N];
int ans;
struct KDTree{
    #define lc tr[i].ch[0]
    #define rc tr[i].ch[1]
    #define mid (l+r)/2
    void build(int &i,int l,int r,vector<int>L,vector<int>R,int type){
        if(l>r){
            return;
        }
        i=++idx;
        cmptype=type;
        nth_element(a+l,a+mid,a+r+1);
        vector<int>L1=L,L2=L,R1=R,R2=R;
        R1[type]=a[mid].x[type],L2[type]=a[mid].x[type];
        build(lc,l,mid-1,L1,R1,(type+1)%3);tr[lc].par=i;
        build(rc,mid+1,r,L2,R2,(type+1)%3);tr[rc].par=i;
        tr[i].l=L,tr[i].r=R,tr[i].x=a[mid].x;
        p[mid]=i;
    }
    void query(int i,vector<int>L,vector<int>R){
        if(!i){
            return;
        }
        if(tr[i].maxn<=ans){
            return;
        }
        auto check=[&](){
            for(register int d=0;d<3;d++){
                if(L[d]>tr[i].l[d]){
                    return 0;
                }
                if(R[d]<tr[i].r[d]){
                    return 0;
                }
            }
            return 1;
        };
        if(check()){
            ans=tr[i].maxn;
            return;
        }
        auto check2=[&](){
            for(register int d=0;d<3;d++){
                if(R[d]<tr[i].l[d]){
                    return 0;
                }
                if(L[d]>tr[i].r[d]){
                    return 0;
                }
            }
            return 1;
        };
        if(!check2()){
            return;
        }
        auto check3=[&](){
            for(register int d=0;d<3;d++){
                if(L[d]>tr[i].x[d]){
                    return 0;
                }
                if(R[d]<tr[i].x[d]){
                    return 0;
                }
            }
            return 1;
        };
        if(check3()){
            ans=max(ans,tr[i].val);
        }
        query(lc,L,R);
        query(rc,L,R);
    }
    void update(int i,int val){
        tr[i].val=max(tr[i].val,val);
        while(i){
            tr[i].maxn=max(tr[i].maxn,val);
            i=tr[i].par;
        }
    }
    #undef lc
    #undef rc
    #undef mid
}kdt;
int n,rt,f[N];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        vector<int>x(3);
        scanf("%d",&a[i].x0);
        for(int j=0;j<3;j++){
            scanf("%d",&x[j]);
        }
        a[i].x=x;
    }
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++){
        a[i].id=i;
    }
    kdt.build(rt,1,n,vector<int>(3,-inf),vector<int>(3,inf),0);
    for(int i=1;i<=n;i++){
        p2[a[i].id]=i;
    }
    int res=0;
    for(int i=1;i<=n;i++){
        ans=0;
        kdt.query(rt,vector<int>(3,-inf),a[p2[i]].x);
        f[i]=ans+1;
        res=max(res,f[i]);
        kdt.update(p[p2[i]],f[i]);
    }
    printf("%d\n",res);
    return 0;
}
2024/6/12 17:09
加载中...