• 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();
        }
    }





  • 相关阅读:
    央企国管公积金提取。本人实际经历 2013年6月5日
    一台机器开启多个tomcat7 绿色版
    给Repeater、Datalist和Datagrid增加自动编号列
    有关比较分析的MDX
    01[转Cognos8第三讲]Cognos8的安装与配置
    BI前端工具对比
    转摘cognos学习笔记
    04[转Cognos8第四讲]权限配置(2)
    如何更改oracle字符集
    IBM Cognos BI 最佳实践: 定制 IBM Cognos 8 UI
  • 原文地址:https://www.cnblogs.com/Cooook/p/7738486.html
Copyright © 2020-2023  润新知