zoukankan      html  css  js  c++  java
  • 【BZOJ4066】简单题(KD-Tree)

    【BZOJ4066】简单题(KD-Tree)

    题面

    BZOJ

    题解

    如果这题不卡空间,并且不强制在线的话
    显然可以用(CDQ)分治做

    但是它又卡空间又强制在线,于是我们欢快的来用(KD-Tree)吧。

    (KD-Tree)维护每一个点,每次询问的时候
    判断询问的矩形和当前矩形的交
    如果全部覆盖直接加上所有的和
    如果没有交则直接返回
    如果有部分交则递归处理。

    我用了两种方案防止(KD-Tree)被卡
    第一种:定时重构。大概就是每插入(10000)次后就重构一次

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 100200
    #define mid o
    #define ls (t[o].ch[0])
    #define rs (t[o].ch[1])
    #define cmin(a,b) (a<b?a:a=b)
    #define cmax(a,b) (a>b?a:a=b)
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    const double alpha=0.762333;
    int D;
    struct Node{int d[2],v;}a[MAX];
    bool operator<(Node a,Node b){return a.d[D]<b.d[D];}
    struct KD_Node
    {
        int mn[2],mx[2],ch[2];
        Node a;
        int sum;
        void clear(){mn[0]=mn[1]=mx[0]=mx[1]=a.d[0]=a.d[1]=a.v=sum=0;}
    }t[MAX];
    int tot,Num;
    void update(int x,int y)
    {
        cmin(t[x].mn[0],t[y].mn[0]);cmin(t[x].mn[1],t[y].mn[1]);
        cmax(t[x].mx[0],t[y].mx[0]);cmax(t[x].mx[1],t[y].mx[1]);
    }
    void pushup(int o)
    {
        t[o].mn[0]=t[o].mx[0]=t[o].a.d[0];
        t[o].mn[1]=t[o].mx[1]=t[o].a.d[1];
        t[o].sum=t[ls].sum+t[rs].sum+t[o].a.v;
        if(ls)update(o,ls);if(rs)update(o,rs);
    }
    int Build(int l,int r,int nd)
    {
        int mid=(l+r)>>1;D=nd;
        nth_element(&a[l],&a[mid],&a[r+1]);
        t[o].a=a[mid];
        if(l<mid)ls=Build(l,mid-1,nd^1);else ls=0;
        if(r>mid)rs=Build(mid+1,r,nd^1);else rs=0;
        pushup(o);return o;
    }
    void insert(int &o,int nd,Node a)
    {
        if(!o){o=tot;t[o].a=a;pushup(o);return;}
        if(t[o].a.d[nd]<a.d[nd])insert(rs,nd^1,a);
        else insert(ls,nd^1,a);
        pushup(o);
    }
    int checksame(KD_Node a,int x1,int x2,int y1,int y2)
    {
        if(x1<=a.mn[0]&&a.mx[0]<=x2&&y1<=a.mn[1]&&a.mx[1]<=y2)return 1;//all
        if(x2<a.mn[0]||a.mx[0]<x1)return 0;
        if(y2<a.mn[1]||a.mx[1]<y1)return 0;
        return 2;
    }
    int Query(int o,int x1,int x2,int y1,int y2)
    {
        int ret=0;
        if(t[o].a.d[0]>=x1&&t[o].a.d[0]<=x2&&t[o].a.d[1]>=y1&&t[o].a.d[1]<=y2)
            ret+=t[o].a.v;
        if(ls)
        {
            int d=checksame(t[ls],x1,x2,y1,y2);
            if(d==1)ret+=t[ls].sum;
            if(d==2)ret+=Query(ls,x1,x2,y1,y2);
        }
        if(rs)
        {
            int d=checksame(t[rs],x1,x2,y1,y2);
            if(d==1)ret+=t[rs].sum;
            if(d==2)ret+=Query(rs,x1,x2,y1,y2);
        }
        return ret;
    }
    int N,rt;
    int main()
    {
        N=read();
        int lans=0,opt,x,y,A,x1,y1,x2,y2;
        while(233)
        {
            opt=read();
            if(opt==3)break;
            if(opt==1)
            {
                x=read()^lans,y=read()^lans,A=read()^lans;
                insert(rt,0,a[++tot]=(Node){x,y,A});
                if(tot%10000==0)rt=Build(1,tot,0);
            }
            else
            {
                x1=read()^lans,y1=read()^lans,x2=read()^lans,y2=read()^lans;
                printf("%d
    ",lans=Query(rt,x1,x2,y1,y2));
            }
        }
    }
    

    第二种:类似替罪羊树,当不满足平衡因子时,把子树拍掉重构。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 200200
    #define ls (t[o].ch[0])
    #define rs (t[o].ch[1])
    #define cmin(a,b) (a<b?a:a=b)
    #define cmax(a,b) (a>b?a:a=b)
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    const double alpha=0.75;
    int D;
    struct Node{int d[2],v;}a[MAX];
    bool operator<(Node a,Node b){return a.d[D]<b.d[D];}
    struct KD_Node
    {
        int mn[2],mx[2],ch[2];
        Node a;
        int sum,size;
        void clear(){mn[0]=mn[1]=mx[0]=mx[1]=a.d[0]=a.d[1]=a.v=sum=size=0;}
    }t[MAX];
    int Q[MAX],top;
    int tot,Num;
    int NewNode()
    {
        if(!top)return ++tot;
        t[Q[top]].clear();
        return Q[top--];
    }
    void update(int x,int y)
    {
        cmin(t[x].mn[0],t[y].mn[0]);cmin(t[x].mn[1],t[y].mn[1]);
        cmax(t[x].mx[0],t[y].mx[0]);cmax(t[x].mx[1],t[y].mx[1]);
    }
    void pushup(int o)
    {
        t[o].mn[0]=t[o].mx[0]=t[o].a.d[0];
        t[o].mn[1]=t[o].mx[1]=t[o].a.d[1];
        t[o].size=t[ls].size+t[rs].size+1;
        t[o].sum=t[ls].sum+t[rs].sum+t[o].a.v;
        if(ls)update(o,ls);if(rs)update(o,rs);
    }
    int Build(int l,int r,int nd)
    {
        int mid=(l+r)>>1;D=nd;
        nth_element(&a[l],&a[mid],&a[r+1]);
        int o=NewNode();
        t[o].a=a[mid];
        if(l<mid)ls=Build(l,mid-1,nd^1);else ls=0;
        if(r>mid)rs=Build(mid+1,r,nd^1);else rs=0;
        pushup(o);return o;
    }
    void kill(int o){if(ls)kill(ls);a[++Num]=t[o].a;Q[++top]=o;if(rs)kill(rs);}
    void checker(int &o,int nd)
    {
        if(alpha*t[o].size<t[ls].size||alpha*t[o].size<t[rs].size)
            Num=0,kill(o),o=Build(1,Num,nd);
    }
    void insert(int &o,int nd,Node a)
    {
        if(!o){o=NewNode();t[o].a=a;pushup(o);return;}
        if(t[o].a.d[nd]<a.d[nd])insert(rs,nd^1,a);
        else insert(ls,nd^1,a);
        pushup(o);checker(o,nd);
    }
    int checksame(KD_Node a,int x1,int x2,int y1,int y2)
    {
        if(x1<=a.mn[0]&&a.mx[0]<=x2&&y1<=a.mn[1]&&a.mx[1]<=y2)return 1;//all
        if(x2<a.mn[0]||a.mx[0]<x1)return 0;
        if(y2<a.mn[1]||a.mx[1]<y1)return 0;
        return 2;
    }
    int Query(int o,int x1,int x2,int y1,int y2)
    {
        int ret=0;
        if(t[o].a.d[0]>=x1&&t[o].a.d[0]<=x2&&t[o].a.d[1]>=y1&&t[o].a.d[1]<=y2)
            ret+=t[o].a.v;
        if(ls)
        {
            int d=checksame(t[ls],x1,x2,y1,y2);
            if(d==1)ret+=t[ls].sum;
            if(d==2)ret+=Query(ls,x1,x2,y1,y2);
        }
        if(rs)
        {
            int d=checksame(t[rs],x1,x2,y1,y2);
            if(d==1)ret+=t[rs].sum;
            if(d==2)ret+=Query(rs,x1,x2,y1,y2);
        }
        return ret;
    }
    int N,rt;
    int main()
    {
        N=read();
        int lans=0,opt,x,y,A,x1,y1,x2,y2;
        while(233)
        {
            opt=read();
            if(opt==3)break;
            if(opt==1)
            {
                x=read()^lans,y=read()^lans,A=read()^lans;
                insert(rt,0,(Node){x,y,A});
            }
            else
            {
                x1=read()^lans,y1=read()^lans,x2=read()^lans,y2=read()^lans;
                printf("%d
    ",lans=Query(rt,x1,x2,y1,y2));
            }
        }
    }
    
    
  • 相关阅读:
    BSGS
    斯特林数 笔记
    「CF932E」Team Work
    「hihoCoder1869」Items
    「Luogu1345」[USACO5.4]奶牛的电信Telecowmunication
    「Luogu4363/BZOJ5248」[九省联考2018]一双木棋chess
    「Luogu2522」[HAOI2011]Problem b
    狄利克雷卷积学习笔记
    莫比乌斯函数学习笔记
    欧拉函数学习笔记
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9069206.html
Copyright © 2011-2022 走看看