zoukankan      html  css  js  c++  java
  • 题解 P4848/LOJ6016/BZOJ4605【崂山白花蛇草水】

    简化题面

    维护一个二维平面,支持两种操作

    (1),插入一个节点坐标为((x,y))且权值为(v)

    (2),查询矩形范围为(x_0,x_1,y_0,y_1)内第(k)大的节点权值为多少,若不够(k)个则输出NAIVE!ORZzyz.

    强制在线。

    数据范围(nle500000)(qle100000)(1le x, yle n)(1le vle 10^9)(1le x_1le x_2le n)(1le y_1le y_2le n)(1le kle q)

    解题思路

    二维平面内插入节点查询范围内信息首先想到用(mathcal{KDtree})维护,但是考虑查询第(k)大如何进行维护,考虑建立一棵权值线段树,查询时在权值线段树上二分。则在权值线段树的每一个节点上,我们维护一个(mathcal{KDtree})即可,插入的时候直接在对应的线段树上的(log)个节点上将节点插入相应的(mathcal{KDtree})上,(mathcal{KDtree})上维护每个节点的(size)即可。

    因为是第(k)大,因此二分的时候要以右儿子的(size)为判断标准

    注意权值线段树需要动态开点要不然空间会炸掉,(mathcal{KDtree})维护节点插入的时候应当注意失衡时和替罪羊树一样重构即可。

    复杂度我不太会分析,大概是一个插入复杂度(O(nlog^2 nlogv))和一个查询复杂度(O(nsqrt nlogv))

    (mathcal{Code})

    // 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 maxv = 1e9;
    const i32 kato = 5e5 + 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 , q , x , y , z , t , k , opt , lastans = 0;
    
    struct point{
        i32 x , y , val;
        point(i32 x = 0 , i32 y = 0 , i32 val = 0): x(x) , y(y) , val(val){ }
        friend bool operator !=(const point &a , const point &b){
            return a.x != b.x || a.y != b.y;
        }
    }b[kato];
    
    inline bool cmp1(const point &a , const point &b){
        return a.x < b.x;
    }
    
    inline bool cmp2(const point &a , const point &b){
        return a.y < b.y;
    }
    
    namespace K_D_tree{
        struct node{
            node *ls , *rs;
            static queue<node*> q;
            point p;
            i32 x1 , x2 , y1 , y2 , size;
            node(){ }
            node(const point &qaq): p(qaq){
                ls = rs = 0x0 , x1 = x2 = p.x , y1 = y2 = p.y , size = 1;
            }
            inline void up1(node *x){
                this -> x1 = min(this -> x1 , x -> x1) , this -> x2 = max(this -> x2 , x -> x2);
                this -> y1 = min(this -> y1 , x -> y1) , this -> y2 = max(this -> y2 , x -> y2);
            }
            inline void up2(){
                size = (this -> ls ? this -> ls -> size : 0) + (this -> rs ? this -> rs -> size : 0) + 1;
            }
            void *operator new(size_t){
                static node *S = 0x0 , *T = 0x0; node *tmp;
                return q.empty() ? (S == T && (T = (S = new node[1024]) + 1024 , S == T) ? 0x0 : S ++) : (tmp = q.front() , q.pop() , tmp); 
            }
            void operator delete(void *qaq){ q.push(static_cast<node*>(qaq)); }
        };
    
        queue<node*> node::q;
    
        i32 tot , top;
    
        inline void del(node *&o){
            if(o -> ls) del(o -> ls);
            if(o -> rs) del(o -> rs);
            b[++ tot] = o -> p , delete(o);
        }
    
        inline node *build(node *fa , i32 l , i32 r , i32 opt , point *a){
            if(l > r) return 0x0;
            i32 mid = (l + r) >> 1;
            nth_element(a + l , a + mid , a + r + 1 , opt ? cmp2 : cmp1);
            node *o = new node(a[mid]);
            o -> ls = build(o , l , mid - 1 , opt ^ 1 , a);
            o -> rs = build(o , mid + 1 , r , opt ^ 1 , a);
            if(o -> ls) o -> up1(o -> ls);
            if(o -> rs) o -> up1(o -> rs);
            o -> up2();
            return 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 , b);
        }
    
        inline void insert(node *&o , const point &p , i32 opt){
            if(!o) return void(o = new node(p));
            if(opt == 1){
                if(p.y <= o -> p.y) insert(o -> ls , p , opt ^ 1);
                else insert(o -> rs , p , opt ^ 1);
            }else{
                if(p.x <= o -> p.x) insert(o -> ls , p , opt ^ 1);
                else insert(o -> rs , p , opt ^ 1);
            }
            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 x1 , i32 x2 , i32 y1 , i32 y2){
            if(!o || x2 < o -> x1 || x1 > o -> x2 || y2 < o -> y1 || y1 > o -> y2) return 0;
            if(x1 <= o -> x1 && o -> x2 <= x2 && y1 <= o -> y1 && o -> y2 <= y2) return o -> size;
            i32 res = 0;
            if(x1 <= o -> p.x && o -> p.x <= x2 && y1 <= o -> p.y && o -> p.y <= y2) res += 1;
            return res + ask(o -> ls , x1 , x2 , y1 , y2) + ask(o -> rs , x1 , x2 , y1 , y2);
        }
    }
    
    namespace Segement_Tree{
        struct node{
            node *ls , *rs;
            K_D_tree::node *p;
        }_pool[kato] = {{_pool , _pool , 0x0}} , *tail = _pool , *null = tail ++ , *root = null;
        
        inline void insert(node *&o , i32 l , i32 r , const point &p , i32 k){
            if(o == null) o = new(tail ++) node(*null);
            K_D_tree::insert(o -> p , p , 0); 
            if(l == r) return;
            i32 mid = (l + r) >> 1;
            if(k <= mid) insert(o -> ls , l , mid , p , k);
            else insert(o -> rs , mid + 1 , r , p , k);
        }
    
        inline i32 ask(node *o , i32 l , i32 r , i32 x1 , i32 x2 , i32 y1 , i32 y2 , i32 k){
            if(l == r) return l;
            i32 res = K_D_tree::ask(o -> rs -> p , x1 , x2 , y1 , y2);
            i32 mid = (l + r) >> 1;
            if(k > res) return ask(o -> ls , l , mid , x1 , x2 , y1 , y2 , k - res);
            else return ask(o -> rs , mid + 1 , r , x1 , x2 , y1 , y2 , k);
        }
    }
    
    inline int Ame_(){
    #ifdef AME__
        freopen(".in" , "r" , stdin); freopen(".out" , "w" , stdout); int nol_cl = clock();
    #endif
        mian(n) , mian(q);
        for(; q --> 0 ;){
            mian(opt);
            if(opt == 1){ mian(x) , mian(y) , mian(k) , x ^= lastans , y ^= lastans , k ^= lastans , Segement_Tree::insert(Segement_Tree::root , 0 , maxv , point(x , y) , k); }
            if(opt == 2){ mian(x) , mian(y) , mian(z) , mian(t) , mian(k) , x ^= lastans , y ^= lastans , z ^= lastans , t ^= lastans , k ^= lastans; if((lastans = Segement_Tree::ask(Segement_Tree::root , 0 , maxv , x , z , y , t , k))) TOWA("%d
    " , lastans); else TOWA("NAIVE!ORZzyz.
    "); }
        }
    #ifdef AME__TIME
        LOG("Time: %dms
    ", int((clock() - nol_cl) / (qwq)CLOCKS_PER_SEC * 1000));
    #endif
        return ~~(0^_^0); /*さようならプログラム*/
    }
        
    int Ame__ = Ame_();
        
    int main(){;}
    
    呐,这份感情,什么时候可以传达呢
  • 相关阅读:
    pycharm远程SSH调用服务器python解释器教程
    SVN自动生成版本号信息
    gtest运行小析
    记一次问题排查心得
    Effective STL读书笔记
    模板单例实现
    NetLimiter网速测试小坑
    客户端升级项目小结
    长训总结
    科目二心得体会
  • 原文地址:https://www.cnblogs.com/Ame-sora/p/14425262.html
Copyright © 2011-2022 走看看