zoukankan      html  css  js  c++  java
  • BZOJ 4605 崂山白花蛇草水(权值线段树+KD树)

    【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=4605

    【题目大意】

      操作 1 x y k 表示在点(x,y)上放置k个物品,
      操作 2 x0 y0 x1 y1 k 表示查询矩形内放置物品第k多的格子有几个物品
      同一个格子不会被同时放置物品一次以上

    【题解】

      内层用替罪羊式的KD树动态维护加点,和查询矩形内点数
      外层用权值线段树维护KD树的权值编号
      对于每个权值点,添加到权值线段树查询路径上的每一颗KD树上,
      这样就保证了区间的二进制拆分区间总可以被查询到

    【代码】

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N=3000000,INF=1e9;
    namespace KD_Tree{
        struct Dot{  
            int d[2],mn[2],mx[2],l,r,sz;  
            Dot(){l=r=0;}  
            Dot(int x,int y){d[0]=x;d[1]=y;l=r=0;}  
            int& operator [] (int x){return d[x];}  
        };  
        int D,dcnt=0;
        Dot T[N];
        inline void umax(int&a,int b){if(a<b)a=b;}
        inline void umin(int&a,int b){if(a>b)a=b;}
        inline bool cmp(int x,int y){return T[x][D]<T[y][D];}
        inline void up(int x){
            T[x].sz=T[T[x].l].sz+T[T[x].r].sz+1;
            T[x].mn[0]=T[x].mx[0]=T[x][0];  
            T[x].mn[1]=T[x].mx[1]=T[x][1]; 
            if(T[x].l){
                umax(T[x].mx[0],T[T[x].l].mx[0]);
                umin(T[x].mn[0],T[T[x].l].mn[0]);   
                umax(T[x].mx[1],T[T[x].l].mx[1]);
                umin(T[x].mn[1],T[T[x].l].mn[1]);
            }
            if(T[x].r){
                umax(T[x].mx[0],T[T[x].r].mx[0]);
                umin(T[x].mn[0],T[T[x].r].mn[0]);
                umax(T[x].mx[1],T[T[x].r].mx[1]);
                umin(T[x].mn[1],T[T[x].r].mn[1]);
            }
        }
        inline int NewDot(int x,int y){
            ++dcnt; 
            T[dcnt][0]=x; T[dcnt][1]=y;
            return up(dcnt),dcnt;
        }
        int query(int x,int x0,int y0,int x1,int y1){
            if(!x||T[x].mn[0]>x1||T[x].mx[0]<x0||T[x].mn[1]>y1||T[x].mx[1]<y0)return 0;  
            if(T[x].mn[0]>=x0&&T[x].mx[0]<=x1&&T[x].mn[1]>=y0&&T[x].mx[1]<=y1)return T[x].sz;  
            int res=0;  
            if(T[x][0]>=x0&&T[x][0]<=x1&&T[x][1]>=y0&&T[x][1]<=y1)res++;  
            return res+query(T[x].l,x0,y0,x1,y1)+query(T[x].r,x0,y0,x1,y1); 
        }
        int tot=0,pt[N]; 
        int gt,gtd,gtf;
        const double alp=0.8;
        inline bool isbad(int x){  
            return max(T[T[x].l].sz,T[T[x].r].sz)>T[x].sz*alp+5;  
        }
        void ins(int&x,int D,const Dot&p){  
            if(!x){x=NewDot(p.d[0],p.d[1]);return;}  
            if(p.d[D]<T[x][D])ins(T[x].l,D^1,p);  
            else ins(T[x].r,D^1,p);  
            up(x);  
            if(isbad(x))gt=x,gtd=D,gtf=0;  
            else if(gt==T[x].l||gt==T[x].r)gtf=x;  
        }
        void treavel(int&x){  
            if(!x)return;  
            pt[++tot]=x;  
            treavel(T[x].l),treavel(T[x].r);  
        }
        int build(int l,int r,int now){  
            if(l>r)return 0;  
            int mid=(l+r)>>1,x;  
            D=now;  
            nth_element(pt+l,pt+mid,pt+r+1,cmp);  
            x=pt[mid];  
            T[x].l=build(l,mid-1,now^1);  
            T[x].r=build(mid+1,r,now^1);  
            return up(x),x;  
        } 
        void Insert(int&x,const Dot&p){  
            gt=gtf=0,ins(x,0,p);  
            if(!gt)return;  
            tot=0,treavel(gt);  
            if(!gtf){x=build(1,tot,gtd);return;}  
            if(gt==T[gtf].l)T[gtf].l=build(1,tot,gtd);  
            else T[gtf].r=build(1,tot,gtd);  
        } 
    }
    int tot=0;
    struct data{int rt,l,r;}T[N];
    void Insert(int &x,const KD_Tree::Dot&p,int val,int l=1,int r=INF){
        if(!x)x=++tot;
        KD_Tree::Insert(T[x].rt,p);
        if(l==r)return;
        int mid=(l+r)>>1;
        if(val<=mid)Insert(T[x].l,p,val,l,mid);
        else Insert(T[x].r,p,val,mid+1,r);
    }
    int query(int x,int x0,int y0,int x1,int y1,int k,int l=1,int r=INF){  
        if(l==r)return l;  
        int rcnt=KD_Tree::query(T[T[x].r].rt,x0,y0,x1,y1);  
        int mid=(l+r)>>1;  
        if(k<=rcnt)return query(T[x].r,x0,y0,x1,y1,k,mid+1,r);  
        return query(T[x].l,x0,y0,x1,y1,k-rcnt,l,mid);  
    }
    int n,q,op,x0,y0,x1,y1,k,root=0,ans=0;  
    int main(){
        scanf("%d%d",&n,&q);
        while(q--){
            scanf("%d",&op);
            if(op==1){
                scanf("%d%d%d",&x0,&y0,&k);
                x0^=ans,y0^=ans,k^=ans;
                KD_Tree::Dot p=KD_Tree::Dot(x0,y0);
                Insert(root,p,k);
            }else{
                scanf("%d%d%d%d%d",&x0,&y0,&x1,&y1,&k);
                x0^=ans,y0^=ans,x1^=ans,y1^=ans,k^=ans;
                int res=KD_Tree::query(T[root].rt,x0,y0,x1,y1);
                if(res<k)puts("NAIVE!ORZzyz."),ans=0;  
                else printf("%d
    ",ans=query(root,x0,y0,x1,y1,k));  
            }
        }return 0;
    }
  • 相关阅读:
    2015长春区域赛感想
    己亥清爽恢复系列之数据文件1篇:SYSTEM物理损坏或丢失(关键表空间)
    ecshop和jQuery冲突
    ecshop广告分析
    ecshop商品页增加编辑器fckeditor
    DIV自适应高度
    打个招呼
    jdk的wsimport方法实现webservice客户端调用服务
    jdk自带发布webservice服务
    Mysql数据库基本配置
  • 原文地址:https://www.cnblogs.com/forever97/p/bzoj4605.html
Copyright © 2011-2022 走看看