zoukankan      html  css  js  c++  java
  • luogu P4148 简单题

    传送门

    这题真简单,直接把(CDQ)给ban掉了

    其实数据范围比较小可以直接二维树状数组,我们看数据范围,发现点的个数比N还小,可以考虑用一些奇怪的数据结构

    说的就是你,(KD tree)

    (KD tree)就是一个K维的二叉查找树(是吧),一维的二叉查找树就是我们所熟悉的平衡树,所以考虑用平衡树的方法维护,插入一个点就跟平衡树插一个点类似.查找的话,如果当前范围完全被查询范围完全包含就直接加上范围值,如果有交就递归处理,没交就不管

    注意维护整棵(KD tree)使其平衡,可以考虑替罪羊树,如果某个儿子子树大小>子树*(alpha)就将整棵子树暴力重构

    细节详见代码 其实是不想写了

    #include<bits/stdc++.h>
    #define LL long long
    #define db double
    #define il inline
    #define re register
    #define ft first
    #define sc second
    #define mkpr make_pair
    
    using namespace std;
    const int N=2e5+10;
    const db alpha=0.72;
    il int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    int dd;
    #define lc (s[o].ch[0])
    #define rc (s[o].ch[1])
    struct point
    {
        int a,d[2];
        bool operator < (const point &bb) const {return d[dd]<bb.d[dd];}
    }pp[N];
    struct node
    {
        int ch[2],mi[2],ma[2],a,sz;
        point p;
        void clr(){ch[0]=ch[1]=mi[0]=mi[1]=ma[0]=ma[1]=a=sz=p.a=0;}
    }s[N];
    il void upd(int o,int x)
    {
        s[o].mi[0]=min(s[o].mi[0],s[x].mi[0]),s[o].mi[1]=min(s[o].mi[1],s[x].mi[1]);
        s[o].ma[0]=max(s[o].ma[0],s[x].ma[0]),s[o].ma[1]=max(s[o].ma[1],s[x].ma[1]);
    }
    il void psup(int o)
    {
        s[o].sz=s[lc].sz+s[rc].sz+1;
        s[o].a=s[lc].a+s[rc].a+s[o].p.a;
        s[o].mi[0]=s[o].ma[0]=s[o].p.d[0],s[o].mi[1]=s[o].ma[1]=s[o].p.d[1];
        if(lc) upd(o,lc);
        if(rc) upd(o,rc);
    }
    int st[N],tp,tt,m;
    il int newnode()
    {
        if(!tp) return ++tt;
        s[st[tp]].clr();
        return st[tp--];
    }
    void del(int o)
    {
        if(lc) del(lc);
        pp[++m]=s[o].p,st[++tp]=o;
        if(rc) del(rc);
    }
    int bui(int l,int r,int d)
    {
        if(l>r) return 0;
        dd=d;
        int mid=(l+r)>>1,o=newnode();
        nth_element(pp+l,pp+mid,pp+r+1);
        s[o].p=pp[mid];
        lc=bui(l,mid-1,d^1),rc=bui(mid+1,r,d^1);
        psup(o);
        return o;
    }
    void inst(int &o,int d,point a)
    {
        if(!o) {o=newnode(),s[o].p=a,psup(o);return;}
        int mid=(s[o].mi[d]+s[o].ma[d])>>1;
        if(a.d[d]<=mid) inst(lc,d^1,a);
        else inst(rc,d^1,a);
        psup(o);
        if((db)s[o].sz*alpha<(db)max(s[lc].sz,s[rc].sz)) m=0,del(o),o=bui(1,m,d);
    }
    int quer(int o,int lx,int ly,int rx,int ry)
    {
        int an=0;
        if(lx<=s[o].p.d[0]&&ly<=s[o].p.d[1]&&rx>=s[o].p.d[0]&&ry>=s[o].p.d[1]) an+=s[o].p.a;
        if(lc)
        {
            if(lx<=s[lc].mi[0]&&ly<=s[lc].mi[1]&&rx>=s[lc].ma[0]&&ry>=s[lc].ma[1]) an+=s[lc].a;
            else if(max(lx,s[lc].mi[0])<=min(rx,s[lc].ma[0])&&max(ly,s[lc].mi[1])<=min(ry,s[lc].ma[1])) an+=quer(lc,lx,ly,rx,ry);
        }
        if(rc)
        {
            if(lx<=s[rc].mi[0]&&ly<=s[rc].mi[1]&&rx>=s[rc].ma[0]&&ry>=s[rc].ma[1]) an+=s[rc].a;
            else if(max(lx,s[rc].mi[0])<=min(rx,s[rc].ma[0])&&max(ly,s[rc].mi[1])<=min(ry,s[rc].ma[1])) an+=quer(rc,lx,ly,rx,ry);
        }
        return an;
    }
    int n,rt,ans;
    
    int main()
    {
        n=rd();
        while(233)
        {
            int op=rd();
            if(op==1)
            {
                int x=rd()^ans,y=rd()^ans,z=rd()^ans;
                inst(rt,0,(point){z,x,y});
            }
            else if(op==2)
            {
                int lx=rd()^ans,ly=rd()^ans,rx=rd()^ans,ry=rd()^ans;
                printf("%d
    ",ans=quer(rt,lx,ly,rx,ry));
            }
            else break;
        }
        return 0;
    }
    
  • 相关阅读:
    PAT乙级-1037. 在霍格沃茨找零钱(20)
    PAT乙级-1041. 考试座位号(15)
    PAT乙级-1047. 编程团体赛(20)
    css3 实现 背景图片显示
    块级元素与行内元素(内联元素)的区别和联系
    JS变量
    导航条菜单的制作 滑动缓慢
    HTML中Id和Name的区别
    全面理解Javascript中Function对象的属性和方法
    理解盒子模型
  • 原文地址:https://www.cnblogs.com/smyjr/p/10410325.html
Copyright © 2011-2022 走看看