题解 P3769 【[CH弱省胡策R2]TATT】

Luogu

简化题面

求点数最多的四维偏序路径

解题思路

三维偏序可以直接第一层排序然后用\(\mathcal{CDQ}\)分治,转化成二位偏序问题来做,呢么四维偏序怎么做呢

\(\mathcal{Solution1}\)

众所周知,\(\mathcal{KD}\) \(tree\)可以用来解决多维坐标问题,且在随机数据下复杂度很优秀,呢么我们来用\(\mathcal{KD}\) \(tree\)来解决这个问题。

还是和四维偏序一样,先对第一位排序,我们用\(\mathcal{KD}\) \(tree\)来维护三维的坐标

对于显然的\(dp\)方程我们有

\[dp_i = \max_{x_j\le x_i,y_j\le y_i,z_j \le z_i} dp_j + 1 \]

呢么我们维护三维范围内的最大值,每次查询的范围为\(x\in [-INF,x_i],y\in [-INF,y_i],z\in [-INF,z_i]\)内的最大值即可,然后每次结束之后插入节点,失衡时和替罪样树那样重构\(\mathcal{KD}\) \(tree\)即可

\(\mathcal{Code1}\)

// Author: Ame__
#include<bits/stdc++.h>
#include<stdint.h>
#define _ 0
#define AME__DEBUG
#define bomb exit(0)
#define LOG(FMT...) fprintf(stderr , FMT)
#define TOWA(FMT...) fprintf(stdout , FMT)
using namespace std;
/*Grievous Lady*/
    
typedef int32_t i32;
typedef int64_t i64;
typedef double qwq;
    
const int BUF_SIZE = 1 << 12;
char buf[BUF_SIZE] , *buf_s = buf , *buf_t = buf + 1;
    
#define PTR_NEXT() \
{ \
    buf_s ++; \
    if(buf_s == buf_t) \
    { \
        buf_s = buf; \
        buf_t = buf + fread(buf , 1 , BUF_SIZE , stdin); \
    } \
}
    
#define mians(_s_) \
{ \
    while(!isgraph(*buf_s)) PTR_NEXT();\
    char register *_ptr_ = (_s_); \
    while(isgraph(*buf_s) || *buf_s == '-') \
    { \
        *(_ptr_ ++) = *buf_s; \
        PTR_NEXT(); \
    } \
    (*_ptr_) = '\0'; \
}
    
template <typename _n_> void mian(_n_ & _x_){
    while(*buf_s != '-' && !isdigit(*buf_s)) PTR_NEXT();
    bool register _nega_ = false; if(*buf_s == '-'){ _nega_ = true; PTR_NEXT(); }
    _x_ = 0; while(isdigit(*buf_s)){ _x_ = _x_ * 10 + *buf_s - '0'; PTR_NEXT(); } if(_nega_) _x_ = -_x_;
}
    
const i32 INF = 0x3f3f3f3f;
const i32 kato = 2e5 + 10;

template <typename _n_> bool cmax(_n_ &a , const _n_ &b){ return a < b ? a = b , 1 : 0; }
template <typename _n_> bool cmin(_n_ &a , const _n_ &b){ return a > b ? a = b , 1 : 0; }
    
i32 n , ans;

struct point{
    i32 a , b , c , d , val;
    point(i32 a = 0 , i32 b = 0 , i32 c = 0 , i32 d = 0 , i32 val = 0): a(a) , b(b) , c(c) , d(d) , val(val){ }
    friend bool operator !=(const point &x , const point &y){
        return x.a != y.a || x.b != y.b || x.c != y.c || x.d != y.d;
    }
}f[kato] , h[kato];

inline bool cmp1(const point &x , const point &y){
    return x.b < y.b;
}

inline bool cmp2(const point &x , const point &y){
    return x.c < y.c;
}

inline bool cmp3(const point &x , const point &y){
    return x.d < y.d;
}

struct node{
    i32 a , b , c , d;
    node(i32 a = 0 , i32 b = 0 , i32 c = 0 , i32 d = 0): a(a) , b(b) , c(c) , d(d){ }
    friend bool operator <(const node &x , const node &y){
        return x.a ^ y.a ? x.a < y.a : x.b ^ y.b ? x.b < y.b : x.c ^ y.c ? x.c < y.c : x.d < y.d;
    }
}g[kato];

namespace towa{
    struct node{
        node *ls , *rs;
        point p;
        i32 b1 , b2 , c1 , c2 , d1 , d2 , val , mval , size;
        node(){ }
        node(const point &qaq): p(qaq){
            ls = rs = 0x0 , b1 = b2 = p.b , c1 = c2 = p.c , d1 = d2 = p.d , mval = val = p.val , size = 1;
        }
        inline void up1(node *x){
            this -> b1 = min(this -> b1 , x -> b1) , this -> b2 = max(this -> b2 , x -> b2);
            this -> c1 = min(this -> c1 , x -> c1) , this -> c2 = max(this -> c2 , x -> c2);
            this -> d1 = min(this -> d1 , x -> d1) , this -> d2 = max(this -> d2 , x -> d2);
        }
        inline void up2(){
            mval = max(this -> val , max(this -> ls ? this -> ls -> mval : -INF , this -> rs ? this -> rs -> mval : -INF));
            size = (this -> ls ? this -> ls -> size : 0) + (this -> rs ? this -> rs -> size : 0) + 1;
        }
    }*root , _pool[kato] , *tail = _pool , *sta[kato];

    i32 top , tot;

    inline node *build(node *fa , i32 l , i32 r , i32 opt){
        if(l > r) return 0x0;
        i32 mid = (l + r) >> 1;
        nth_element(h + l , h + mid , h + r + 1 , opt == 1 ? cmp2 : opt == 2 ? cmp3 : cmp1);
        node *o = new(top ? sta[top --] : tail ++) node(h[mid]);
        o -> ls = build(o , l , mid - 1 , (opt + 1) % 3);
        o -> rs = build(o , mid + 1 , r , (opt + 1) % 3);;
        if(o -> ls) o -> up1(o -> ls);
        if(o -> rs) o -> up1(o -> rs);
        o -> up2();
        return o;
    }

    inline void del(node *&o){
        if(!o) return;
        if(o -> ls) del(o -> ls);   
        if(o -> rs) del(o -> rs);
        h[++ tot] = o -> p , sta[++ top] = o;
    }

    inline void judge(node *&o , i32 opt){
        tot = 0; i32 res = o -> size;
        if(0.725 * o -> size <= static_cast<qwq>(max(o -> ls ? o -> ls -> size : 0 , o -> rs ? o -> rs -> size : 0))) del(o) , o = build(0x0 , 1 , res , opt);
    }

    inline void insert(node *&o , const point &a , i32 opt){
        if(!o) return void(o = new(top ? sta[top --] : tail ++) node(a));
        if(opt == 2){
            if(a.d <= o -> p.d) insert(o -> ls , a , (opt + 1) % 3);
            else insert(o -> rs , a , (opt + 1) % 3);
        }else if(opt == 1){
            if(a.c <= o -> p.c) insert(o -> ls , a , (opt + 1) % 3);
            else insert(o -> rs , a , (opt + 1) % 3);
        }else{
            if(a.b <= o -> p.b) insert(o -> ls , a , (opt + 1) % 3);
            else insert(o -> rs , a , (opt + 1) % 3);
        }
        if(o -> ls) o -> up1(o -> ls);
        if(o -> rs) o -> up1(o -> rs);
        o -> up2();
        judge(o , opt);
    }

    inline i32 ask(node *o , i32 b1 , i32 b2 , i32 c1 , i32 c2 , i32 d1 , i32 d2){
        if(!o || b2 < o -> b1 || b1 > o -> b2 || c2 < o -> c1 || c1 > o -> c2 || d2 < o -> d1 || d1 > o -> d2) return 0;
        if(b1 <= o -> b1 && o -> b2 <= b2 && c1 <= o -> c1 && o -> c2 <= c2 && d1 <= o -> d1 && o -> d2 <= d2) return o -> mval;
        i32 res = 0;
        if(b1 <= o -> p.b && o -> p.b <= b2 && c1 <= o -> p.c && o -> p.c <= c2 && d1 <= o -> p.d && o -> p.d <= d2) res = max(res , o -> val);
        return max(res , max(ask(o -> ls , b1 , b2 , c1 , c2 , d1 , d2) , ask(o -> rs , b1 , b2 , c1 , c2 , d1 , d2)));
    }
}

inline int Ame_(){
#ifdef AME__
    freopen(".in" , "r" , stdin); freopen(".out" , "w" , stdout); int nol_cl = clock();
#endif
    mian(n);
    for(i32 i = 1;i <= n;i ++) mian(g[i].a) , mian(g[i].b) , mian(g[i].c) , mian(g[i].d);
    sort(g + 1 , g + 1 + n);
    for(i32 i = 1;i <= n;i ++) f[i] = (point){0 , g[i].b , g[i].c , g[i].d};
    for(i32 i = 1;i <= n;i ++){
        i32 res = towa::ask(towa::root , -INF , f[i].b , -INF , f[i].c , -INF , f[i].d) + 1;
        f[i].val = res;
        ans = max(ans , res);
        towa::insert(towa::root , f[i] , 0);
    }
    TOWA("%d\n" , ans);
#ifdef AME__TIME
    LOG("Time: %dms\n", int((clock() - nol_cl) / (qwq)CLOCKS_PER_SEC * 1000));
#endif
    return ~~(0^_^0); /*さようならプログラム*/
}
    
int Ame__ = Ame_();
    
int main(){;}

\(\mathcal{Solution2}\)

\(\mathcal{CDQ}\)\(\mathcal{CDQ}\),暂时鸽鸽鸽

posted @ 2021-02-19 21:32  Ame_sora  阅读(48)  评论(0编辑  收藏  举报