BZOJ_2716_[Violet 3]天使玩偶&&BZOJ_2648_SJY摆棋子_KDTree
BZOJ_2716_[Violet 3]天使玩偶&&BZOJ_2648_SJY摆棋子_KDTree
Description
Input
Output
Sample Input
1 1
2 3
2 1 2
1 3 3
2 4 2
Sample Output
2
HINT
kdtree可以过
kdtree是主要处理多维空间信息的工具。
当k=2时通常用来解决矩形查询问题,已知的一些矩形查询问题复杂度可以证明。
不过由于kdtree的实质看起来像剪枝,处理其他问题时也有很优越的时间。
kdtree像是一棵BST,它对于每层找到坐标为中位数的点当做这个点维护的信息,然后递归左右。
建树时通常横着切一刀竖着切一刀,再用nth_element来保证复杂度。
每个节点维护子树信息,mx[p][0]和mn[p][0]表示横坐标的范围,纵坐标同理。
通常插入点的时候要保证平衡而重构kdtree。
对于这道题我们维护出kdtree的信息。
查询时面对ls和rs两个矩形,分别求出他们的估价dis,即查询点到两个矩形的曼哈顿最小距离。
先递归dis小的那个,然后再判断答案和dis的关系决定是否递归另一棵子树。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1000050
#define ls ch[p][0]
#define rs ch[p][1]
#define _min(x,y) ((x)<(y)?(x):(y))
#define _max(x,y) ((x)>(y)?(x):(y))
int mx[N][2],mn[N][2],ch[N][2],now,root,ans,n,m,dep[N],maxdep;
inline char nc() {
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int rd() {
int x=0; char s=nc();
while(s<'0'||s>'9') s=nc();
while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+s-'0',s=nc();
return x;
}
char pbuf[100000],*pp=pbuf;
void push(const char ch) {
if(pp-pbuf==100000) fwrite(pbuf,1,100000,stdout),pp=pbuf;
*pp++=ch;
}
void write(int x) {
static char sta[35];
int top=0;
do{sta[++top]=x%10,x/=10;}while(x);
while(top) push(sta[top--]+'0');
push('\n');
}
struct Point {
int p[2];
bool operator < (const Point &u) const {
return p[now]==u.p[now]?p[!now]<u.p[!now]:p[now]<u.p[now];
}
}a[N];
int Abs(int x) {return x>0?x:-x;}
void pushup(int p,int x) {
mx[p][0]=_max(mx[p][0],mx[x][0]);
mx[p][1]=_max(mx[p][1],mx[x][1]);
mn[p][0]=_min(mn[p][0],mn[x][0]);
mn[p][1]=_min(mn[p][1],mn[x][1]);
}
int build(int l,int r,int type,int fa) {
int mid=(l+r)>>1;
dep[mid]=dep[fa]+1;
maxdep=_max(maxdep,dep[mid]);
now=type;
nth_element(a+l,a+mid,a+r+1);
mx[mid][0]=mn[mid][0]=a[mid].p[0];
mx[mid][1]=mn[mid][1]=a[mid].p[1];
if(l<mid) ch[mid][0]=build(l,mid-1,!type,mid),pushup(mid,ch[mid][0]);
if(r>mid) ch[mid][1]=build(mid+1,r,!type,mid),pushup(mid,ch[mid][1]);
return mid;
}
void insert(int x) {
int p=root;
now=0;
while(1) {
pushup(p,x);
if(a[x].p[now]<a[p].p[now]) {
if(ls) p=ls;
else {ls=x; pushup(p,x); dep[x]=dep[p]+1; break;}
}else {
if(rs) p=rs;
else {rs=x; pushup(p,x); dep[x]=dep[p]+1; break;}
}
now=now^1;
}
maxdep=_max(maxdep,dep[x]);
if(maxdep>100) maxdep=0,root=build(1,n,0,0);
}
int getdis(int x,int y,int p) {
int re=0;
if(x<mn[p][0]) re+=mn[p][0]-x;
if(x>mx[p][0]) re+=x-mx[p][0];
if(y<mn[p][1]) re+=mn[p][1]-y;
if(y>mx[p][1]) re+=y-mx[p][1];
return re;
}
void query(int x,int y,int p) {
int re=Abs(x-a[p].p[0])+Abs(y-a[p].p[1]),dl,dr;
if(re<ans) ans=re;
dl=ls?getdis(x,y,ls):0x3f3f3f3f;
dr=rs?getdis(x,y,rs):0x3f3f3f3f;
if(dl<dr) {
if(dl<ans) query(x,y,ls);
if(dr<ans) query(x,y,rs);
}else {
if(dr<ans) query(x,y,rs);
if(dl<ans) query(x,y,ls);
}
}
int main() {
n=rd(); m=rd();
int i,opt,x,y;
for(i=1;i<=n;i++) a[i].p[0]=rd(),a[i].p[1]=rd();
root=build(1,n,0,0);
while(m--) {
opt=rd(); x=rd(); y=rd();
if(opt==1) n++,a[n].p[0]=mx[n][0]=mn[n][0]=x,a[n].p[1]=mx[n][1]=mn[n][1]=y,insert(n);
else ans=0x3f3f3f3f,query(x,y,root),write(ans);
}
fwrite(pbuf,1,pp-pbuf,stdout);
}
BZOJ_2716_[Violet 3]天使玩偶&&BZOJ_2648_SJY摆棋子_KDTree的更多相关文章
- bzoj2716/2648 / P4169 [Violet]天使玩偶/SJY摆棋子
P4169 [Violet]天使玩偶/SJY摆棋子 k-d tree 模板 找了好几天才发现输出优化错了....真是zz...... 当子树非常不平衡时,就用替罪羊树的思想,拍扁重建. luogu有个 ...
- 【LG4169】[Violet]天使玩偶/SJY摆棋子
[LG4169][Violet]天使玩偶/SJY摆棋子 题面 洛谷 题解 至于\(cdq\)分治的解法,以前写过 \(kdTree\)的解法好像还\(sb\)一些 就是记一下子树的横.纵坐标最值然后求 ...
- 洛谷 P4169 [Violet]天使玩偶/SJY摆棋子 解题报告
P4169 [Violet]天使玩偶/SJY摆棋子 题目描述 \(Ayu\)在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,\(Ayu\) 却忘了她把天使玩偶埋在了哪 ...
- luoguP4169 [Violet]天使玩偶/SJY摆棋子 K-Dtree
P4169 [Violet]天使玩偶/SJY摆棋子 链接 luogu 思路 luogu以前用CDQ一直过不去. bzoj还是卡时过去的. 今天终于用k-dtree给过了. 代码 #include &l ...
- 洛谷P4169 [Violet]天使玩偶/SJY摆棋子(CDQ分治)
[Violet]天使玩偶/SJY摆棋子 题目传送门 解题思路 用CDQ分治开了氧气跑过. 将输入给的顺序作为第一维的时间,x为第二维,y为第三维.对于距离一个询问(ax,ay),将询问分为四块,左上, ...
- [Violet]天使玩偶/SJY摆棋子 [cdq分治]
P4169 [Violet]天使玩偶/SJY摆棋子 求离 \((x,y)\) 最近点的距离 距离的定义是 \(|x1-x2|+|y1-y2|\) 直接cdq 4次 考虑左上右上左下右下就可以了-略微卡 ...
- 天使玩偶/SJY摆棋子
P4169 [Violet]天使玩偶/SJY摆棋子 CDQ分治的题目. 我们发现题目要我们求的\(|A_x-B_x|+|A_y-B_y|\)的绝对值号比较恶心. 试想一下怎么去掉 如果所有的点都在我们 ...
- P4169 [Violet]天使玩偶/SJY摆棋子
题目背景 感谢@浮尘ii 提供的一组hack数据 题目描述 Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里,所以她决定仅 ...
- LG4169 [Violet]天使玩偶/SJY摆棋子
题意 Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里,所以她决定仅凭一点模糊的记忆来寻找它. 我们把 Ayu 生活的小镇 ...
随机推荐
- JMeter 压力測试使用函数和 CSV 文件參数化 json 数据
在 http Load Testing 中.json 数据的提交是个让人头疼的问题.本文具体介绍怎样进行 JMeter 的 json 測试提交,以及怎样将其參数化. St ...
- Linux以下基于TCP多线程聊天室(server)
接上篇博文,本文是server端的实现,主要实现的功能,就是现实client的连接.转发client发送的消息.以及client掉线提示等功能,同一时候能够在这这上面扩展和TCP以及线程相关的功能木块 ...
- andrid对不能导入的类,知道类路径怎样使用该类
andrid对不能导入的类,知道类路径怎样使用该类?使用java的反射机制. 下边是一个样例. MTK平台对Android源生的Telephone接口进行了扩展,加入了一个TelephonyManag ...
- C 标准库 - <float.h>
C 标准库 - <float.h> 简介 C 标准库的 float.h 头文件包含了一组与浮点值相关的依赖于平台的常量.这些常量是由 ANSI C 提出的,这让程序更具有可移植性.在讲解这 ...
- Oracle数据库字符集解释
转自:http://www.itpub.net/thread-836643-1-1.html Pl/SQL 执行select * from nls_database_parameters---可以查看 ...
- mysql 中遇到金额 BigDecimal类型字段
当数据库字段为BigDecimal型,and后面判断去掉. 否则当为0时候,视为空处理了.即传参为null
- php 获取当前页面url路径
#测试网址: http://localhost/blog/testurl.php?id=5 //获取域名或主机地址 echo $_SERVER['HTTP_HOST'].""; # ...
- 02 svn 文件提交与目录结构
一:文件操作给svn服务器提交程序文件: ① 在被提交文件的身上点击右键------> tortoiseSVN----->add ② 在被提交文件身上点击右键------> comm ...
- 封装EF code first用存储过程的分页方法
一年半没有做过MVC的项目了,还是很怀念(因为现在项目还是原来的ASPX),个人还是喜欢mvc,最近又开始重拾MVC,感觉既熟悉又陌生. 记录一下封装好的分页代码 首先先说下 我使用EF codefi ...
- P1355 神秘大三角
题目描述 判断一个点与已知三角形的位置关系. 输入输出格式 输入格式: 前三行:每行一个坐标,表示该三角形的三个顶点 第四行:一个点的坐标,试判断该点与前三个点围成三角形的位置关系 (详见样例) 所有 ...