zoukankan      html  css  js  c++  java
  • 题解 P3769 【[CH弱省胡策R2]TATT】

    Luogu

    简化题面

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

    解题思路

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

    (mathcal{Solution1})

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

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

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

    [dp_i = max_{x_jle x_i,y_jle y_i,z_j le z_i} dp_j + 1 ]

    呢么我们维护三维范围内的最大值,每次查询的范围为(xin [-INF,x_i],yin [-INF,y_i],zin [-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_) = ''; 
    }
        
    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
    " , ans);
    #ifdef AME__TIME
        LOG("Time: %dms
    ", int((clock() - nol_cl) / (qwq)CLOCKS_PER_SEC * 1000));
    #endif
        return ~~(0^_^0); /*さようならプログラム*/
    }
        
    int Ame__ = Ame_();
        
    int main(){;}
    

    (mathcal{Solution2})

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

    呐,这份感情,什么时候可以传达呢
  • 相关阅读:
    [Trie][并查集]JZOJ 5822 量子纠缠
    [模拟]JZOJ 5820 非法输入
    SAM模板
    [树形DP]JZOJ 5819 大逃杀
    [MST][dij]JZOJ 5818 做运动
    [暴力]JZOJ 5817 抄代码
    [概率期望][树形DP][LCA]JZOJ 5814 树
    认证组件
    注册接口
    视图家族 & 路由组件
  • 原文地址:https://www.cnblogs.com/Ame-sora/p/14418086.html
Copyright © 2011-2022 走看看