P4169 [Violet]天使玩偶/SJY摆棋子
题目背景
感谢@浮尘ii 提供的一组hack数据
题目描述
Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下。而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里,所以她决定仅凭一点模糊的记忆来寻找它。
我们把 Ayu 生活的小镇看作一个二维平面坐标系,而 Ayu 会不定时地记起可能在某个点 (xmy) 埋下了天使玩偶;或者 Ayu 会询问你,假如她在 (x,y) ,那么她离近的天使玩偶可能埋下的地方有多远。
因为 Ayu 只会沿着平行坐标轴的方向来行动,所以在这个问题里我们定义两个点之间的距离为dist(A,B)=|Ax-Bx|+|Ay-By|。其中 Ax 表示点 A的横坐标,其余类似。
输入输出格式
输入格式:
第一行包含两个整数n和m ,在刚开始时,Ayu 已经知道有n个点可能埋着天使玩偶, 接下来 Ayu 要进行m 次操作
接下来n行,每行两个非负整数 (xi,yi),表示初始n个点的坐标。
再接下来m 行,每行三个非负整数 t,xi,yi。
如果t=1 ,则表示 Ayu 又回忆起了一个可能埋着玩偶的点 (xi,yi) 。
如果t=2 ,则表示 Ayu 询问如果她在点 (xi,yi) ,那么在已经回忆出来的点里,离她近的那个点有多远
输出格式:
对于每个t=2 的询问,在单独的一行内输出该询问的结果。
输入输出样例
2 3
1 1
2 3
2 1 2
1 3 3
2 4 2
1
2
说明
n,m<=300 000
xi,yi<=1 000 000
Solution:
本题巨说是点分治裸题。。。然而我用$kd-tree$水了波$90$。(应该是可以$A$的,但是暂时不会玄学转树,留坑待填~)
有必要先解释一下变量含义:$(d[0],d[1])$为当前根节点的坐标,$(mn[0],mn[1])$表示当前节点代表的二维平面中最左下角的坐标,$(mx[0],mx[1])$表示最右上角的坐标,$l,r$分别表示当前节点的左、右儿子。
思路比较简单,构建二维搜索树,将每个点拍到面上去,从根节点往下每层交替按$x$和$y$为关键字建树。
建树过程,要尽可能使得树保持平衡,所以每次以区间中间为当前根节点建树,二维平面分为左部和右部两部分,分别表示当前节点的左儿子和右儿子。
代码:
#include<bits/stdc++.h>
#define il inline
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define Min(a,b) ((a)>(b)?(b):(a))
#define Max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int N=,inf=;
int n,m,x,y,opt,ans,cmpd,root;
struct node{
int d[],l,r,mn[],mx[];
bool operator <(const node a){
return ((d[cmpd]<a.d[cmpd])||(d[cmpd]==a.d[cmpd]&&d[!cmpd]<a.d[!cmpd]));
}
}t[N]; il int gi(){
int a=;char x=getchar();bool f=;
while((x<''||x>'')&&x!='-')x=getchar();
if(x=='-')x=getchar(),f=;
while(x>=''&&x<='')a=(a<<)+(a<<)+x-,x=getchar();
return f?-a:a;
} il void update(int rt){
int ls=t[rt].l,rs=t[rt].r;
if(ls){
t[rt].mn[]=Min(t[rt].mn[],t[ls].mn[]);
t[rt].mn[]=Min(t[rt].mn[],t[ls].mn[]);
t[rt].mx[]=Max(t[rt].mx[],t[ls].mx[]);
t[rt].mx[]=Max(t[rt].mx[],t[ls].mx[]);
}
if(rs){
t[rt].mn[]=Min(t[rt].mn[],t[rs].mn[]);
t[rt].mn[]=Min(t[rt].mn[],t[rs].mn[]);
t[rt].mx[]=Max(t[rt].mx[],t[rs].mx[]);
t[rt].mx[]=Max(t[rt].mx[],t[rs].mx[]);
}
} il int build(int l,int r,int tw){
cmpd=tw;
int mid=l+r>>;
nth_element(t+l+,t+mid+,t+r+);
t[mid].mn[]=t[mid].mx[]=t[mid].d[];
t[mid].mn[]=t[mid].mx[]=t[mid].d[];
if(l!=mid)t[mid].l=build(l,mid-,!tw);
if(r!=mid)t[mid].r=build(mid+,r,!tw);
update(mid);
return mid;
} il void insert(int rt){
int op=,p=root;
while(){
if(t[rt].mn[]<t[p].mn[])t[p].mn[]=t[rt].mn[];
if(t[rt].mn[]<t[p].mn[])t[p].mn[]=t[rt].mn[];
if(t[rt].mx[]>t[p].mx[])t[p].mx[]=t[rt].mx[];
if(t[rt].mx[]>t[p].mx[])t[p].mx[]=t[rt].mx[];
if(t[rt].d[op]>=t[p].d[op]){
if(!t[p].r){t[p].r=rt;return;}
else p=t[p].r;
}
else {
if(!t[p].l){t[p].l=rt;return;}
else p=t[p].l;
}
op=!op;
}
} il int mhd(int rt,int x,int y){
int s=;
if(x<t[rt].mn[])s+=(t[rt].mn[]-x);
if(x>t[rt].mx[])s+=(x-t[rt].mx[]);
if(y<t[rt].mn[])s+=(t[rt].mn[]-y);
if(y>t[rt].mx[])s+=(y-t[rt].mx[]);
return s;
} il void query(int rt){
int d0,dl,dr;
d0=abs(t[rt].d[]-x)+abs(t[rt].d[]-y);
if(d0<ans)ans=d0;
if(t[rt].l)dl=mhd(t[rt].l,x,y);
else dl=inf;
if(t[rt].r)dr=mhd(t[rt].r,x,y);
else dr=inf;
if(dl<dr){
if(dl<ans)query(t[rt].l);
if(dr<ans)query(t[rt].r);
}
else {
if(dr<ans)query(t[rt].r);
if(dl<ans)query(t[rt].l);
}
} int main(){
n=gi(),m=gi();
For(i,,n) t[i].d[]=gi(),t[i].d[]=gi();
root=build(,n,);
while(m--){
opt=gi(),x=gi(),y=gi();
if(opt==){
n++;
t[n].mn[]=t[n].mx[]=t[n].d[]=x;
t[n].mn[]=t[n].mx[]=t[n].d[]=y;
insert(n);
}
else {
ans=inf;
query(root);
printf("%d\n",ans);
}
}
return ;
}
P4169 [Violet]天使玩偶/SJY摆棋子的更多相关文章
- bzoj2716/2648 / P4169 [Violet]天使玩偶/SJY摆棋子
P4169 [Violet]天使玩偶/SJY摆棋子 k-d tree 模板 找了好几天才发现输出优化错了....真是zz...... 当子树非常不平衡时,就用替罪羊树的思想,拍扁重建. luogu有个 ...
- 洛谷 P4169 [Violet]天使玩偶/SJY摆棋子 解题报告
P4169 [Violet]天使玩偶/SJY摆棋子 题目描述 \(Ayu\)在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,\(Ayu\) 却忘了她把天使玩偶埋在了哪 ...
- 洛谷P4169 [Violet]天使玩偶/SJY摆棋子(CDQ分治)
[Violet]天使玩偶/SJY摆棋子 题目传送门 解题思路 用CDQ分治开了氧气跑过. 将输入给的顺序作为第一维的时间,x为第二维,y为第三维.对于距离一个询问(ax,ay),将询问分为四块,左上, ...
- 洛谷P4169 [Violet]天使玩偶/SJY摆棋子
%%%神仙\(SJY\) 题目大意: 一个二维平面,有两种操作: \(1.\)增加一个点\((x,y)\) \(2.\)询问距离\((x,y)\)曼哈顿最近的一个点有多远 \(n,m\le 300 0 ...
- Luogu P4169 [Violet]天使玩偶/SJY摆棋子
传送门 二维平面修改+查询,cdq分治可以解决. 求关于某个点曼哈顿距离(x,y坐标)最近的点——dis(A,B) = |Ax-Bx|+|Ay-By| 但是如何去掉绝对值呢? 查看题解发现假设所有的点 ...
- luoguP4169 [Violet]天使玩偶/SJY摆棋子 K-Dtree
P4169 [Violet]天使玩偶/SJY摆棋子 链接 luogu 思路 luogu以前用CDQ一直过不去. bzoj还是卡时过去的. 今天终于用k-dtree给过了. 代码 #include &l ...
- [Violet]天使玩偶/SJY摆棋子 [cdq分治]
P4169 [Violet]天使玩偶/SJY摆棋子 求离 \((x,y)\) 最近点的距离 距离的定义是 \(|x1-x2|+|y1-y2|\) 直接cdq 4次 考虑左上右上左下右下就可以了-略微卡 ...
- 【LG4169】[Violet]天使玩偶/SJY摆棋子
[LG4169][Violet]天使玩偶/SJY摆棋子 题面 洛谷 题解 至于\(cdq\)分治的解法,以前写过 \(kdTree\)的解法好像还\(sb\)一些 就是记一下子树的横.纵坐标最值然后求 ...
- LG4169 [Violet]天使玩偶/SJY摆棋子
题意 Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里,所以她决定仅凭一点模糊的记忆来寻找它. 我们把 Ayu 生活的小镇 ...
随机推荐
- 最优布线问题(wire.cpp)
最优布线问题(wire.cpp) [问题描述] 学校有n台计算机,为了方便数据传输,现要将它们用数据线连接起来.两台计算机被连接是指它们间有数据线连接.由于计算机所处的位置不同,因此不同的两台计算机的 ...
- springboot 中controller 返回html界面或 jsp界面
参考链接:https://blog.csdn.net/qq_15260315/article/details/80907056 经尝试,返回html界面没问题,但是返回jsp界面是有问题的,just ...
- Python中的矩阵操作
Numpy 通过观察Python的自有数据类型,我们可以发现Python原生并不提供多维数组的操作,那么为了处理矩阵,就需要使用第三方提供的相关的包. NumPy 是一个非常优秀的提供矩阵操作的包.N ...
- 前端--再遇jQuery
一.属性 属性(如果你的选择器选出了多个对象,那么默认只会返回第一个属性) attr(属性名|属性值) --一个参数是获取属性的值,两个参数是设置属性值 --点击图片加载示例 removeAttr(属 ...
- python全栈开发-前方高能-生成器和生成器表达式
python_day_13 今日主要内容1. 生成器和生成器函数生成器的本质就是迭代器生成器的三种创建办法: 1.通过生成器函数 2.通过生成器表达式创建生成器 3.通过数据转换 生成器函数: 函数中 ...
- html面试题总结
1.请描述一个网页从开始请求到最终显示的完整过程? 1).在浏览器中输入网址: 2).发送至DNS服务器并获得域名对应的WEB服务器的IP地址: 3).与WEB服务器简历TCP连接: 4).浏览器向W ...
- 01_基于TCP的循环为同一个客户端下载文件的下载器
原版: TCP分为客户端(client)和服务器(server),每次服务器只能为客户端提供一次的下载服务. 改良版: TCP分为客户端(client)和服务器(server), (1)每次服务器能为 ...
- java引用Arcface,实现人脸识别(demo)
## 开发环境准备: ###开发使用到的软件和工具: * Jdk8.mysql5.7.libarcsoft_face.dll(so).libarcsoft_face_engine.dll(so).li ...
- JavaScript 高级之面向对象
1. 对象属性及方法 创建对象的方式 <script> //创建对象的方式一 var obj = {}; //创建对象的方式一 var obj = new Object(); </s ...
- 根据Unicode码生成汉字
最近需要一批汉字字符数据,类似数字字符与ASCII码之间的对应关系,汉字字符与Unicode码之间也存在对应关系. 所以可以遍历Unicode码批量生成汉字. 其中,汉字为宽字符,输出时候注意需要修改 ...