zoukankan      html  css  js  c++  java
  • BZOJ 4605 崂山白花蛇草水 权值线段树+K-D树

    Description

    神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水。凭借着神犇Aleph的实
    力,他轻松地进了山东省省队,现在便是他履行诺言的时候了。蒟蒻Bob特地为他准备了999,999,999,999,999,999
    瓶崂山白花蛇草水,想要灌神犇Aleph。神犇Aleph求(跪着的)蒟蒻Bob不要灌他,由于神犇Aleph是神犇,蒟蒻Bo
    b最终答应了他的请求,但蒟蒻Bob决定将计就计,也让神犇Aleph回答一些问题。具体说来,蒟蒻Bob会在一个宽敞
    的广场上放置一些崂山白花蛇草水(可视为二维平面上的一些整点),然后询问神犇Aleph在矩形区域(x1, y1), (
    x2, y2)(x1≤x2且y1≤y2,包括边界)中,崂山白花蛇草水瓶数第k多的是多少。为了避免麻烦,蒟蒻Bob不会在同
    一个位置放置两次或两次以上的崂山白花蛇草水,但蒟蒻Bob想为难一下神犇Aleph,希望他能在每次询问时立刻回
    答出答案。神犇Aleph不屑于做这种问题,所以把这个问题交给了你。

    Input

    输入的第一行为两个正整数N, Q,表示横纵坐标的范围和蒟蒻Bob的操作次数(包括放置次数和询问次数)。
    接下来Q行,每行代表蒟蒻Bob的一个操作,操作格式如下:
    首先第一个数字type,表示操作种类。type=1表示放置,type=2表示询问。
    若type=1,接下来会有三个正整数x, y, v,表示在坐标整点(x, y)放置v瓶崂山白花蛇草水。(1≤x, y≤N, 1≤v≤10^9)
    若type=2,接下来会有五个正整数x1, y1, x2, y2, k,表示询问矩形区域(x1, y1), (x2, y2)中,崂山白花蛇草水瓶数第k多的是多少。
    (1≤x1≤x2≤N,1≤y1≤y2≤N,1≤k≤Q)
    为了体现程序的在线性,你需要将每次读入的数据(除了type值)都异或lastans,其中lastans表示上次询问的答
    案。如果上次询问的答案为"NAIVE!ORZzyz."(见样例输出),则将lastans置为0。初始时的lastans为0。
    初始时平面上不存在崂山白花蛇草水。
    本题共有12组测试数据。对于所有的数据,N≤500,000。
    Q的范围见下表:
    测试点1-2     Q=1,000
    测试点3-7     Q=50,000
    测试点8-12     Q=100,000

    Output

    对于每个询问(type=2的操作),回答崂山白花蛇草水瓶数第k多的是多少。若不存在第k多的瓶数,
    请输出"NAIVE!ORZzyz."(输出不含双引号)。

    Sample Input

    10 7
    1 1 1 1
    1 2 2 3
    1 4 1 2
    1 3 4 4
    2 1 1 4 1 3
    2 2 2 3 5 4
    2 2 1 4 4 2

    Sample Output

    NAIVE!ORZzyz.
    NAIVE!ORZzyz.
    3
    麻麻我树套树一A辣!!

    这题一看就是树套树的裸题啊

    首先要查k小值,那么就要在外面来颗权值线段树,然后像主席树查询一样查询,那么就需要排名,排名是矩形里的点的个数,用K-D树维护一下就好了!。

    代码略长

    #include <stdio.h>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    using std::min;
    using std::max;
    using std::nth_element;
    const double alpha = 0.755;
    const int MAXN = 100005;
    const int inf = 1000000000;
    int now,x0,x1,y0,y1,len,Ans,n,Q;
    
    
    template<typename _t>
    inline _t read(){
        _t x=0,f=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
        for(;isdigit(ch);ch=getchar())x=x*10+(ch^48);
        return x*f;
    }
    
    struct Point{
        int d[2];
        inline int& operator [](int x){return d[x];}
        inline bool operator < (const Point &a)const{
            return d[now]==a.d[now]?d[now^1]<a.d[now^1]:d[now]<a.d[now];
        }
    }pt[MAXN];
    
    struct node{
        node *ls,*rs;
        Point point;
        int mn[2],mx[2],s,split;
        inline void Update(node *p){
            if(!p)return;
            for(int i=0;i<=1;i++)mn[i]=min(mn[i],p->mn[i]);
            for(int i=0;i<=1;i++)mx[i]=max(mx[i],p->mx[i]);
        }
    
        inline void Maintain(){
            s=1;mn[0]=mx[0]=point[0];mn[1]=mx[1]=point[1];
            if(ls)s+=ls->s,Update(ls);
            if(rs)s+=rs->s,Update(rs);
        }
    
        inline bool in(int x0,int y0,int x1,int y1){
            return x0<=mn[0]
            && x1>=mx[0]
            && y0<=mn[1]
            && y1>=mx[1];
        }
    
        inline bool out(int x0,int y0,int x1,int y1){
            return mn[0]>x1
            || mx[0]<x0
            || mn[1]>y1
            || mx[1]<y0;
        }
    
        inline bool self(int x0,int y0,int x1,int y1){
            return point[0]>=x0
            && point[0]<=x1
            && point[1]>=y0
            && point[1]<=y1;
        }
    
        node(Point x,int sp){
            split = sp;
            ls = rs= NULL;
            point = x;s=1;
            mn[0]=mx[0]=x[0];
            mn[1]=mx[1]=x[1];
        }
        node(){}
    
        void* operator new(size_t);
        void operator delete(void *p);
    
        #define size(x) ((x)?(x)->s:(0))
        inline bool bad(){return size(ls)>=s*alpha||size(rs)>=s*alpha;}
    }*C,*mempool,*need;
    std::vector<node*>bin;
    
    void build(node *&o,int l,int r,int d=0){
        if(l>r){o=NULL;return;}
        now = d;int mid = l+r>>1;
        nth_element(&pt[l],&pt[mid],&pt[r+1]);
        o = new node(pt[mid],now);
        build(o->ls,l,mid-1,d^1);
        build(o->rs,mid+1,r,d^1);
        o->Maintain();
    }
    
    void* node :: operator new(size_t){
        node *p;
        if(!bin.empty()){
            p = bin.back();
            bin.pop_back();
        }
        else{
            if(C==mempool){
                C=new node[1<<15];
                mempool=C+(1<<15);
            }
            p=C++;
        }
        return p;
    }
    
    void node::operator delete(void* p){
        bin.push_back((node*)p);
    }
    
    int Query(node *o){
        if(!o)return 0;
        if(o->in(x0,y0,x1,y1))return o->s;
        if(o->out(x0,y0,x1,y1))return 0;
        int Ans = 0;
        if(o->self(x0,y0,x1,y1))Ans ++;
        return Ans+Query(o->ls)+Query(o->rs);
    }
    
    void dfs(node *p){
        if(!p)return;
        dfs(p->ls);
        pt[++len]=p->point;
        dfs(p->rs);
        delete p;
    }
    
    inline void rebuild(node *&o){
        len = 0;
        register int split = o->split;dfs(o);
        build(o,1,len,split);
    }
    
    void insert(node *&o,Point po,int d=0){
        if(!o){o=new node(po,d);return;}
        if(po[d]<o->point[d])insert(o->ls,po,d^1);
        else insert(o->rs,po,d^1);
        o->Maintain();
        if(o->bad())need = o;
    }
    
    inline void ins(node *&o,Point po){
        need = NULL;
        insert(o,po);
        if(need!=NULL)rebuild(need);
    }
    
    struct Seg_tree{
        Seg_tree *ls,*rs;
        node *root;
        Seg_tree(){
            ls=rs=NULL;
            root=NULL;
        }
    }*root;
    
    void Seg_insert(Seg_tree *&o,int l,int r,Point x,int val){
        if(!o) o = new Seg_tree();
        ins(o->root,x);
        if(l==r)return;
        int mid = l+r>>1;
        if(val<=mid)Seg_insert(o->ls,l,mid,x,val);
        else Seg_insert(o->rs,mid+1,r,x,val);
    }
    
    inline int Seg_Query(Seg_tree *o){
        if(!o)return 0;
        return Query(o->root);
    }
    
    inline void Ask(){
        x0=read<int>()^Ans,y0=read<int>()^Ans,x1=read<int>()^Ans,y1=read<int>()^Ans;
        register int k = read<int>()^Ans;
        if(Seg_Query(root)<k){
            Ans = 0;
            printf("NAIVE!ORZzyz.
    ");
            return;
        }
        int l=1,r=inf;
        Seg_tree *rt=root;
        while(l<r){
            int mid = l+r>>1,ans=Seg_Query(rt->rs);
            if(k>ans)k-=ans,rt=rt->ls,r=mid;
            else rt=rt->rs,l=mid+1;
        }
        printf("%d
    ",Ans=l);
    }
    
    inline void change(){
        Point cur;
        cur[0]=read<int>()^Ans;cur[1]=read<int>()^Ans;
        int val = read<int>()^Ans;
        Seg_insert(root,1,inf,cur,val);
    }
    
    int main(){
        n=read<int>();Q=read<int>();
        while(Q--){
            register int tmp = read<int>();
            if(tmp == 1)change();
            else Ask();
        }
    }





  • 相关阅读:
    我爱Java系列之---【SpringBoot打成war包部署】
    279. Perfect Squares
    矩阵dfs--走回路
    112. Path Sum
    542. 01 Matrix
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    Invert Binary Tree
    563 Binary Tree Tilt
    145 Binary Tree Postorder Traversal
  • 原文地址:https://www.cnblogs.com/Cooook/p/7738486.html
Copyright © 2011-2022 走看看