zoukankan      html  css  js  c++  java
  • bzoj3290: Theresa与数据结构

    Description

    【题目背景】
           Theresa是个爱思考的女孩……
    【问题描述】
           这是个复杂的世界。人类社会,自然界,还有地球之外的银河……
    每一天日出日落,人来人往,步履匆匆。究竟是为什么呢?那支配着一切的至高无上的法则又是否存在呢?Theresa知道,这个问题并不是一朝一夕就可以解答的,只有在仔细、深入的观察和思考以后,才有可能将所有支离破碎的线索联系起来,从而隐约窥见真实的答案。
    于是,Theresa经常思考生活中遇到的大大小小的问题。为什么港台出版的书籍里印刷的汉字她一个也不认识呢?为什么隔夜的白开水中富含一氧化二氢呢?为什么每年都有一段时间Gmail邮箱上不去呢?……
    为了更加系统、科学地分析这些问题,Theresa决定向你求助。
    长话短说,Theresa想请你帮助她实现一个数据结构。这个数据结构的功能是在空间直角坐标系中维护一个点的集合,并支持以下三类操作:
    1.      ADD x y z             加入一个新的点,点的坐标为(x, y, z)。
    2.      QUERY x y z r      查询在正方体(x, y, z) - (x+r, y+r, z+r)内部的点的数目。
    3.      CANCEL              撤销最近的一次ADD操作。
    其中x, y, z, r均为给出的整数。QUERY操作中,(x, y, z)为正方体的一个顶点的坐标,r为正方体的边长。在正方体边界上的点也算在正方体内部
    这个问题可能过于困难,所以Theresa并不强迫你实现一个高效的数据结构。然而,你必须对每一次QUERY操作给出正确的答案。

    Input

    第一行包含一个整数N,表示最初的点集有N个点。
    接下来N行,每行包含三个整数xiyizi,依次表示每个点的坐标。
    N+2行包含一个整数Q,表示将有Q次操作。
    接下来Q行,每行表示一次操作,格式如题目描述。

    Output

    输出若干行,每行一个整数,依次表示每次查询操作的答案。

    cdq分治 套 cdq分治 套 树状数组维护扫描线,时间复杂度$O((n+q)log^3(n+q))$

    #include<bits/stdc++.h>
    char buf[7000000],*ptr=buf,ob[1500000],*op=ob;
    int _(){
        int x=0,f=1;
        while(*ptr<48)*ptr++=='-'?f=-1:0;
        while(*ptr>47)x=x*10+*ptr++-48;
        return x*f;
    }
    int _c(){
        while(*ptr<33)++ptr;
        int c=*ptr;
        while(*ptr>32)++ptr;
        return c;
    }
    void pr(int x){
        int ss[12],sp=0;
        do ss[++sp]=x%10;while(x/=10);
        while(sp)*op++=ss[sp--]+48;
        *op++=10;
    }
    const int inf=0x3f3f3f3f,N=100007;
    void mins(int&a,int b){if(a>b)a=b;}
    void maxs(int&a,int b){if(a<b)a=b;}
    int n,q;
    struct pos{
        int x,y,z;
        void R(){
            x=_(),y=_(),z=_();
        }
    }ss[N];
    int sp=0,ep=0,qp=0;
    int as[N],tk=0,bit[N*2][2],xs[N*2],xp=0;
    struct ev{
        int x,y,z,id,sgn;
        void ins(){
            if(id>=0)return;
            for(int w=x;w<=xp;w+=w&-w){
                if(bit[w][0]!=tk)bit[w][0]=tk,bit[w][1]=0;
                bit[w][1]+=sgn;
            }
        }
        void sum(){
            if(id<0)return;
            int s=0;
            for(int w=x;w;w-=w&-w)s+=(bit[w][0]==tk?bit[w][1]:0);
            as[id]+=s*sgn;
        }
    }es[N*10],ez[N*10],eb[N*10];
    bool cmpy(const ev&a,const ev&b){return a.y<b.y;}
    bool cmpz(const ev&a,const ev&b){return a.z!=b.z?a.z<b.z:a.id<b.id;}
    void msort(ev*l,ev*m,ev*r){
        ev*p3=eb,*p1=l,*p2=m;
        while(p1!=m&&p2!=r)*p3++=*(p1->y<p2->y?p1:p2)++;
        while(p1!=m)*p3++=*p1++;
        while(p2!=r)*p3++=*p2++;
        memcpy(l,eb,(r-l)*sizeof(ev));
    }
    int c1;
    void cal2(int L,int R){
        c1=0;
        for(int i=L;i<R&&c1<=5;++i)if(ez[i].id<0)++c1;
        if(c1<=5){
            for(int i=L,p=0;i<R;++i)if(ez[i].id>=0){
                for(int j=0;j<p;++j)if(eb[j].x<=ez[i].x&&eb[j].y<=ez[i].y)as[ez[i].id]+=ez[i].sgn*eb[j].sgn;
            }else eb[p++]=ez[i];
            std::sort(ez+L,ez+R,cmpy);
            return;
        }
        int M=L+R>>1;
        cal2(L,M);cal2(M,R);
        ++tk;
        for(int i=M,j=L;i<R;ez[i++].sum())
            for(;j<M&&ez[j].y<=ez[i].y;ez[j++].ins());
        msort(ez+L,ez+M,ez+R);
    }
    void cal1(int L,int R){
        c1=0;
        for(int i=L;i<R;++i)if(es[i].id<0)++c1;
        if(c1<=200){
            for(int i=L,p=0;i<R;++i)if(es[i].id>=0){
                for(int j=0;j<p;++j)if(eb[j].x<=es[i].x&&eb[j].y<=es[i].y&&eb[j].z<=es[i].z)as[es[i].id]+=es[i].sgn*eb[j].sgn;
            }else eb[p++]=es[i];
            return;
        }
        int M=L+R>>1;
        cal1(L,M);cal1(M,R);
        int p=0,p1;
        for(int i=L;i<M;++i)if(es[i].id<0)ez[p++]=es[i];
        p1=p;
        for(int i=M;i<R;++i)if(es[i].id>=0)ez[p++]=es[i];
        std::sort(ez,ez+p,cmpz);
        if(p1&&p1<p)cal2(0,p);
    }
    int main(){
        fread(buf,1,sizeof(buf),stdin)[buf]=0;
        n=_();
        for(int i=0;i<n;++i){
            ss[sp].R();
            es[ep++]=(ev){xs[++xp]=ss[sp].x,ss[sp].y,ss[sp].z,-1,1};
            ++sp;
        }
        q=_();
        for(int i=0;i<q;++i){
            int c=_c();
            if(c=='A'){
                ss[sp].R();
                es[ep++]=(ev){xs[++xp]=ss[sp].x,ss[sp].y,ss[sp].z,-1,1};
                ++sp;
            }else if(c=='C'){
                --sp;
                es[ep++]=(ev){ss[sp].x,ss[sp].y,ss[sp].z,-1,-1};
            }else{
                int x=_(),y=_(),z=_(),r=_();
                es[ep++]=(ev){x+r,y+r,z+r,qp,1};
                es[ep++]=(ev){x+r,y+r,z-1,qp,-1};
                es[ep++]=(ev){x+r,y-1,z+r,qp,-1};
                es[ep++]=(ev){x+r,y-1,z-1,qp,1};
                es[ep++]=(ev){x-1,y+r,z+r,qp,-1};
                es[ep++]=(ev){x-1,y+r,z-1,qp,1};
                es[ep++]=(ev){x-1,y-1,z+r,qp,1};
                es[ep++]=(ev){x-1,y-1,z-1,qp,-1};
                ++qp;
                xs[++xp]=x+r;
                xs[++xp]=x-1;
            }
        }
        std::sort(xs+1,xs+xp+1);
        for(int i=0;i<ep;++i)es[i].x=std::lower_bound(xs+1,xs+xp+1,es[i].x)-xs;
        cal1(0,ep);
        for(int i=0;i<qp;++i)pr(as[i]);
        fwrite(ob,1,op-ob,stdout);
        return 0;
    }
  • 相关阅读:
    文件操作
    三级菜单(低端版VS高端版)
    字符串内置方法
    简单购物车的实现
    pandas常用函数
    1.在CentOS 7上安装Docker
    2. IDEA 在同一工作空间创建多个项目
    7.SpringMVC注解@RequestParam全面解析
    6.@RequiresPermissions 注解说明
    1. 构建第一个SpringBoot工程
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7280222.html
Copyright © 2011-2022 走看看