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;
}
时间: 2024-10-09 04:58:34

bzoj3290: Theresa与数据结构的相关文章

【kd-tree】bzoj3290 Theresa与数据结构

离线所有操作,对所有可能存在的点建立kd-tree,add相当于权值+1,cancel相当于权值-1. 修改操作要记录kd-tree上每个点的fa,从底向上地进行修改. 优化:若一个矩形框的sumv==0,则不进入.记录矩形框的面积时只记录“有意义”的点的(权值为0的不管). #include<cstdio> #include<algorithm> #include<stack> #include<cstring> using namespace std;

[CDQ分治][Treap][树状数组]Theresa与数据结构

Description 这是个复杂的世界.人类社会,自然界,还有地球之外的银河--每一天日出日落,人来人往,步履匆匆.究竟是为什么呢?那支配着一切的至高无上的法则又是否存在呢?Theresa知道,这个问题并不是一朝一夕就可以解答的,只有在仔细.深入的观察和思考以后,才有可能将所有支离破碎的线索联系起来,从而隐约窥见真实的答案.于是,Theresa经常思考生活中遇到的大大小小的问题.为什么港台出版的书籍里印刷的汉字她一个也不认识呢?为什么隔夜的白开水中富含一氧化二氢呢?为什么每年都有一段时间Gma

【数据结构】之散列链表(Java语言描述)

散列链表,在JDK中的API实现是 HashMap 类. 为什么HashMap被称为"散列链表"?这与HashMap的内部存储结构有关.下面将根据源码进行分析. 首先要说的是,HashMap中维护着的是一个数组: transient Node<K,V>[] table; ,数组中的每个元素都是一个 Node 对象.这里的Node是HashMap的一个内部类,代码如下: static class Node<K,V> implements Map.Entry<

旧题新做:从idy的视角看数据结构

“今天你不写总结……!!!” 额…… 还是讲我的吧.这些考试都是idy出的题. 20170121:DFS序. ST表.线段树练习 这是第一次考数据结构. Problem 1. setsum 1 second 给你一个长度为N 的整数序列,支持两种操作: • modity l r val 将区间[l,r] 中的所有数修改为val • query l r 询问区间[l,r] 所有数的和 分析:最简单的线段树,区间更改区间求和.但注意是更改,不是添改,sum与flag需同时覆盖. Problem 2.

数据结构Set和Map

一.数据结构 Set 集合的基本概念:集合是由一组无序且唯一(即不能重复)的项组成的.这个数据结构使用了与有限集合相同的数学概念,应用在计算机的数据结构中.  特点:key 和 value 相同,没有重复的 value.ES6 提供了数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. 1. 如何创建一个 Set const s = new Set([1, 2, 3]); 2.属性 console.log(s.size); // 3 3.Set 类的方法 --set.add(v

数据结构基本概念

什么是数据结构 "数据结构是数据对象,以及存在于该对象的实例和组成实例的数据元素之间的各种联系.这些联系可以通过定义相关的函数来给出"--Sartaj Sahni,<数据结构.算法与应用> "数据结构是ADT(抽象数据类型Abstract Data Type)的物理实现."--Clifford A.Shaffer,<数据结构与算法分析> "数据结构(data structture)是计算机中存储.组织数据的方式.通常情况下,经i想你

分布式缓存技术redis学习系列(二)——详细讲解redis数据结构(内存模型)以及常用命令

Redis数据类型 与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多,常用的数据类型主要有五种:String.List.Hash.Set和Sorted Set. Redis数据类型内存结构分析 Redis内部使用一个redisObject对象来表示所有的key和value.redisObject主要的信息包括数据类型(type).编码方式(encoding).数据指针(ptr).虚拟内存(vm)等.type代表一个value对象具体是何种数

【Python&amp;数据结构】 抽象数据类型 Python类机制和异常

这篇是<数据结构与算法Python语言描述>的笔记,但是大头在Python类机制和面向对象编程的说明上面.我也不知道该放什么分类了..总之之前也没怎么认真接触过基于类而不是独立函数的Python编程,借着本次机会仔细学习一下. 抽象数据类型 最开始的计算机语言,关注的都是如何更加有效率地计算,可以说其目的是计算层面的抽象.然而随着这个行业的不断发展,计算机不仅仅用于计算,开发也不仅只关注计算过程了,数据层面的抽象也变得同样重要.虽然计算机语言一开始就有对数据的抽象,但是那些都只是对一些最基本的

深入浅出分析MySQL索引设计背后的数据结构

在我们公司的DB规范中,明确规定: 1.建表语句必须明确指定主键 2.无特殊情况,主键必须单调递增 对于这项规定,很多研发小伙伴不理解.本文就来深入简出地分析MySQL索引设计背后的数据结构和算法,从而可以帮你释疑如下问题: 1.为什么innodb表需要主键? 2.为什么建议innodb表主键是单调递增? 3.为什么不建议innodb表主键设置过长? B-tree(多路搜索树,并不是二叉的)是一种常见的数据结构.使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度.B通常