离线所有操作,对所有可能存在的点建立kd-tree,add相当于权值+1,cancel相当于权值-1。

修改操作要记录kd-tree上每个点的fa,从底向上地进行修改。

优化:若一个矩形框的sumv==0,则不进入。记录矩形框的面积时只记录“有意义”的点的(权值为0的不管)。

#include<cstdio>
#include<algorithm>
#include<stack>
#include<cstring>
using namespace std;
int f,C;
inline void R(int &x){
C=0;f=1;
for(;C<'0'||C>'9';C=getchar())if(C=='-')f=-1;
for(x=0;C>='0'&&C<='9';C=getchar())(x*=10)+=(C-'0');
x*=f;
}
inline void P(int x){
if(x<10)putchar(x+'0');
else{P(x/10);putchar(x%10+'0');}
}
stack<int>zhan;
#define N 100001
#define KD 3
int dn,n,root,m,qp[2][KD],idn;
struct Node
{
int ch[2],w,minn[KD],maxx[KD],p[KD],sumv,id;
void Init()
{
sumv=w;
for(int i=0;i<KD;++i)
minn[i]=maxx[i]=p[i];
}
}T[N];
bool operator < (const Node &a,const Node &b){return a.p[dn] < b.p[dn];}
inline void pushup(const int &rt)
{
T[rt].sumv=T[rt].w;
for(int i=0;i<2;++i)
if(T[rt].ch[i]/* && T[T[rt].ch[i]].sumv*/)
{
T[rt].sumv+=T[T[rt].ch[i]].sumv;
for(int j=0;j<KD;++j)
{
T[rt].minn[j]=min(T[rt].minn[j],T[T[rt].ch[i]].minn[j]);
T[rt].maxx[j]=max(T[rt].maxx[j],T[T[rt].ch[i]].maxx[j]);
}
}
}
int buildtree(int l=1,int r=n,int d=0)
{
dn=d;
int m=(l+r>>1);
nth_element(T+l,T+m,T+r+1);
T[m].Init();
if(l!=m) T[m].ch[0]=buildtree(l,m-1,(d+1)%KD);
if(m!=r) T[m].ch[1]=buildtree(m+1,r,(d+1)%KD);
pushup(m);
return m;
}
inline bool Inside(const int &o)
{
for(int i=0;i<KD;++i)
if(qp[0][i] > T[o].p[i] || T[o].p[i] > qp[1][i])
return 0;
return 1;
}
inline bool AllInside(const int &o)
{
for(int i=0;i<KD;++i)
if(qp[0][i] > T[o].minn[i] || T[o].maxx[i] > qp[1][i])
return 0;
return 1;
}
inline bool Cross(const int &o)
{
for(int i=0;i<KD;++i)
if(qp[0][i] > T[o].maxx[i] || T[o].minn[i] > qp[1][i])
return 0;
return 1;
}
int ans;
inline void Query(int rt=root)
{
if(Inside(rt)) ans+=T[rt].w;
for(int i=0;i<2;++i)
if(T[rt].ch[i] && Cross(T[rt].ch[i]))
{
if(AllInside(T[rt].ch[i]))
ans+=T[T[rt].ch[i]].sumv;
else if(T[T[rt].ch[i]].sumv)
Query(T[rt].ch[i]);
}
}
int val;
char op[N][7];
int dian[N][KD],rs[N],ids[N],ma[N],fa[N];
void Update()
{
int U=ma[idn];
T[U].w+=val;
T[U].sumv+=val;
U=fa[U];
while(U)
{
T[U].sumv=T[U].w+T[T[U].ch[0]].sumv+T[T[U].ch[1]].sumv;
// pushup(U);
U=fa[U];
}
}
int main()
{
// freopen("theresa9.in","r",stdin);
// freopen("bzoj3290.out","w",stdout);
R(n);
for(int i=1;i<=n;++i)
{
R(T[i].p[0]); R(T[i].p[1]); R(T[i].p[2]);
T[i].id=i;
T[i].w=1;
}
R(m);
for(int i=1;i<=m;++i)
{
scanf("%s",op[i]);
if(op[i][0]=='A')
{
++n;
R(T[n].p[0]); R(T[n].p[1]); R(T[n].p[2]);
T[n].id=n;
ids[i]=n;
zhan.push(n);
}
else if(op[i][0]=='Q')
{
R(dian[i][0]); R(dian[i][1]); R(dian[i][2]); R(rs[i]);
}
else
{
ids[i]=zhan.top();
zhan.pop();
}
}
root=(1+n>>1);
buildtree();
for(int i=1;i<=n;++i)
{
ma[T[i].id]=i;
for(int j=0;j<2;++j)
if(T[i].ch[j])
fa[T[i].ch[j]]=i;
}
for(int i=1;i<=m;++i)
if(op[i][0]=='A')
{
idn=ids[i];
val=1;
Update();
}
else if(op[i][0]=='Q')
{
memcpy(qp[0],dian[i],sizeof(qp[0]));
for(int j=0;j<KD;++j)
qp[1][j]=qp[0][j]+rs[i];
ans=0;
Query();
// printf("%d\n",ans);
P(ans),puts("");
}
else
{
idn=ids[i];
val=-1;
Update();
}
return 0;
}

【kd-tree】bzoj3290 Theresa与数据结构的更多相关文章

  1. BZOJ3290 : Theresa与数据结构

    CANCEL操作可以看作删点,X坐标可以离散化 将询问按Z坐标差分,转化成两个求Z<=某个数的和的询问 将操作CDQ分治 每次将前一半的修改.后一半的查询按照Z坐标排序 然后扫描线,每到一个询问 ...

  2. 【数据结构与算法】k-d tree算法

    k-d tree算法 k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点 ...

  3. 【数据结构】K-D Tree

    K-D Tree 这东西是我入坑 ICPC 不久就听说过的数据结构,但是一直没去学 QAQ,终于在昨天去学了它.还是挺好理解的,而且也有用武之地. 目录 简介 建树过程 性质 操作 例题 简介 K-D ...

  4. 【BZOJ-2648&2716】SJY摆棋子&天使玩偶 KD Tree

    2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2459  Solved: 834[Submit][Status][Discu ...

  5. k-d tree算法

    k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k ...

  6. HDU2966 In case of failure(浅谈k-d tree)

    嘟嘟嘟 题意:给定\(n\)个二维平面上的点\((x_i, y_i)\),求离每一个点最近的点得距离的平方.(\(n \leqslant 1e5\)) 这就是k-d tree入门题了. k-d tre ...

  7. 浅谈K-D Tree

    初步认识\(K-D\) \(Tree\) \(K-D\) \(Tree\)是一种基于空间分割的二叉树形数据结构,一般用于高维信息检索.因为\(OI\)中很多问题都能转化为高维信息检索,所以\(K-D\ ...

  8. [转载]kd tree

    [本文转自]http://www.cnblogs.com/eyeszjwang/articles/2429382.html k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据 ...

  9. 初涉k-d tree

    听说k-d tree是一个骗分的好东西?(但是复杂度差评??? 还听说绍一的kdt常数特别小? KDT是什么 KDT的全称是k-degree tree,顾名思义,这是一种处理多维空间的数据结构. 例如 ...

随机推荐

  1. MySQL远程访问权限 允许远程连接

    1 首先cd / 到根目录,打开mysql控制台 登录数据库  mysql -u root -p 2.授权远程连接 mysql> use mysql; Database changed mysq ...

  2. es6+最佳入门实践(9)

    9.Iterator和for...of 9.1.Iterator是什么? Iterator又叫做迭代器,它是一种接口,为各种不同的数据结构提供统一的访问机制.这里说的接口可以形象的理解为USB接口,有 ...

  3. MyEclipse中代码提醒功能

    一:最近仔细研究了下spring mvc中的代码,自己在配置文件哪里来时出现问题,没有提醒,只好自己搜了下有关的信息.如下 window--->preferences---->java-- ...

  4. 将数据导入hive,再将hive表导入hbase

    将数据到入hive的无分区表,再将无分区表导入hive的有分区表: --备份 create table tds_package_secinfobk as select * from tds_packa ...

  5. [POJ3237]Tree解题报告|树链剖分|边剖

    关于边剖 之前做的大多是点剖,其实转换到边剖非常简单. 我的做法是每个点的点权记录其到父亲节点的边的边权. 只要solve的时候不要把最上面的点记录在内就可以了. Tree Description Y ...

  6. [POJ1595]欧拉线性筛(虽然这道题不需要...)

    欧拉线性筛. 对于它的复杂度的计算大概思考了很久. procedure build_prime; var i,j:longint; begin fillchar(vis,sizeof(vis),tru ...

  7. 面试===Linux试题及答案

    一. 单选题: 1.添加一条静态路由,使到网络196.199.3通过eth2接口出去,用: A. route add -net 196.199.3.0 B. route add -net 196.19 ...

  8. springboot 404返回自定义json(只进入过滤器)

    今天在公司没事干,记一次springboot遇到的一些坑,在百度上也没有搜到类似的问题和答案(或者说 答案不是我想要的) 当我们在SpringBoot遇到了404或者500的错误的时候,你们会怎么办? ...

  9. python 多进程multiprocessing 模块

    multiprocessing 常用方法: cpu_count():统计cpu核数 multiprocessing.cpu_count() active_children() 获取所有子进程 mult ...

  10. [ 总结 ] RHEL6/Centos6 使用OpenLDAP集中管理用户帐号

    使用轻量级目录访问协议(LDAP)构建集中的身份验证系统可以减少管理成本,增强安全性,避免数据复制的问题,并提供数据的一致性.