BZOJ 2648 SJY摆棋子(KD树)
【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=2716
【题目大意】
给出一些点,同时不断插入点和询问某点离插入点最近距离
【题解】
我们对于给定的点直接建树,之后动态插入查询即可,重建会超时,
直接插入就可以过了
【代码】
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=1500000,INF=1e9;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
namespace KD_Tree{
struct Dot{
int d[2],mn[2],mx[2],l,r,sz;
Dot(){l=r=0;}
Dot(int x,int y){d[0]=x;d[1]=y;l=r=sz=0;}
int& operator [] (int x){return d[x];}
};
int D,pt[N],dcnt=0;
Dot T[N],p[N];
bool operator<(Dot a,Dot b){return a[D]<b[D];}
inline void umax(int&a,int b){if(a<b)a=b;}
inline void umin(int&a,int b){if(a>b)a=b;}
inline bool cmp(int x,int y){return T[x][D]<T[y][D];}
inline void up(int x){
T[x].sz=T[T[x].l].sz+T[T[x].r].sz+1;
T[x].mn[0]=T[x].mx[0]=T[x][0];
T[x].mn[1]=T[x].mx[1]=T[x][1];
if(T[x].l){
umax(T[x].mx[0],T[T[x].l].mx[0]);
umin(T[x].mn[0],T[T[x].l].mn[0]);
umax(T[x].mx[1],T[T[x].l].mx[1]);
umin(T[x].mn[1],T[T[x].l].mn[1]);
}
if(T[x].r){
umax(T[x].mx[0],T[T[x].r].mx[0]);
umin(T[x].mn[0],T[T[x].r].mn[0]);
umax(T[x].mx[1],T[T[x].r].mx[1]);
umin(T[x].mn[1],T[T[x].r].mn[1]);
}
}
inline int NewDot(int x,int y){
++dcnt; pt[dcnt]=dcnt;
T[dcnt][0]=x; T[dcnt][1]=y;
return up(dcnt),dcnt;
}
void AddDot(int x,int y){
++dcnt; pt[dcnt]=dcnt;
p[dcnt][0]=x; p[dcnt][1]=y;
}
// 曼哈顿距离估价函数
inline int dist(int p1,int px,int py){
int dis=0;
if(px<T[p1].mn[0])dis+=T[p1].mn[0]-px;
if(px>T[p1].mx[0])dis+=px-T[p1].mx[0];
if(py<T[p1].mn[1])dis+=T[p1].mn[1]-py;
if(py>T[p1].mx[1])dis+=py-T[p1].mx[1];
return dis;
}
//查询(px,py)最近点距离
int ans=0;
inline void ask(int x,int px,int py){
int dl,dr,d0=abs(T[x][0]-px)+abs(T[x][1]-py);
if(d0<ans)ans=d0;
dl=T[x].l?dist(T[x].l,px,py):INF;
dr=T[x].r?dist(T[x].r,px,py):INF;
if(dl<dr){
if(dl<ans)ask(T[x].l,px,py);
if(dr<ans)ask(T[x].r,px,py);
}else{
if(dr<ans)ask(T[x].r,px,py);
if(dl<ans)ask(T[x].l,px,py);
}
}
int query(int x,int px,int py){
ans=INF; ask(x,px,py);
return ans;
}
void Insert(int&x,int D,const Dot&p){
if(!x){x=NewDot(p.d[0],p.d[1]);return;}
if(p.d[D]<T[x][D])Insert(T[x].l,D^1,p);
else Insert(T[x].r,D^1,p);
up(x);
}
// 建树
int build(int l,int r,int now){
int mid=(l+r)>>1;
D=now;
nth_element(p+l,p+mid,p+r+1);
T[mid]=p[mid];
for(int i=0;i<2;i++)T[mid].mn[i]=T[mid].mx[i]=T[mid][i];
if(l<mid)T[mid].l=build(l,mid-1,now^1);
if(r>mid)T[mid].r=build(mid+1,r,now^1);
return up(mid),mid;
}
// 暴力重构
int Rebuild(int l,int r,int now){
if(l>r)return 0;
int mid=(l+r)>>1,x;
D=now;
nth_element(pt+l,pt+mid,pt+r+1,cmp);
x=pt[mid];
T[x].l=Rebuild(l,mid-1,now^1);
T[x].r=Rebuild(mid+1,r,now^1);
return up(x),x;
}
}
int n,m,x,y,root=0,c;
int main(){
n=read(); m=read();
for(int i=1;i<=n;i++)KD_Tree::AddDot(read(),read());
root=KD_Tree::build(1,KD_Tree::dcnt,0);
while(m--){
if(read()==1)KD_Tree::Insert(root,0,KD_Tree::Dot(read(),read()));
else printf("%d\n",KD_Tree::query(root,read(),read()));
// if(KD_Tree::dcnt%5000==0)root=KD_Tree::Rebuild(1,KD_Tree::dcnt,0);
// 重构会超时,不重构能过
}return 0;
}
BZOJ 2648 SJY摆棋子(KD树)的更多相关文章
- bzoj 2648 SJY摆棋子 kd树
题目链接 初始的时候有一些棋子, 然后给两种操作, 一种是往上面放棋子. 另一种是给出一个棋子的位置, 问你离它最近的棋子的曼哈顿距离是多少. 写了指针版本的kd树, 感觉这个版本很好理解. #inc ...
- bzoj 2648 SJY摆棋子 —— K-D树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2648 学习资料:https://blog.csdn.net/zhl30041839/arti ...
- BZOJ 2648: SJY摆棋子(K-D Tree)
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 6051 Solved: 2113[Submit][Status][Discuss] Descript ...
- BZOJ 2648: SJY摆棋子
2648: SJY摆棋子 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2968 Solved: 1011[Submit][Status][Disc ...
- BZOJ 2648: SJY摆棋子 kdtree
2648: SJY摆棋子 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2648 Description 这天,SJY显得无聊.在家自己玩 ...
- bzoj 2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 --kdtree
2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 Time Limit: 20 Sec Memory Limit: 128 MB Description 这天,S ...
- BZOJ 2648 SJY摆棋子(KD Tree)
http://www.lydsy.com/JudgeOnline/problem.php?id=2648 题意: 思路: KDtree模板题. 参考自http://www.cnblogs.com/ra ...
- bzoj 2648 SJY摆棋子——KDtree
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2648 第一道KDtree! 学习资料:https://blog.csdn.net/zhl30 ...
- bzoj 2648: SJY摆棋子【KD-tree】
其实理论上cdq更优 核心是依次取x值.y值的mid作为当前节点,向两边递归建立二叉树,树上维护size:子树大小:mx[0/1]:子树内最大x/y:mn[0/1]:子树内最小x/y:d[0/1]:这 ...
随机推荐
- Java编程思想 4th 第3章 操作符
有了数据,还需要进行数据间的运算,因此Java中也有数据间运算的各种符号,书本称之为操作符,正确的翻译应该是运算符. Java中的运算符同C++相同,运算符同运算符对象构成表达式,表达式是运算对象及运 ...
- weight decay(权值衰减)、momentum(冲量)和normalization
一.weight decay(权值衰减)的使用既不是为了提高你所说的收敛精确度也不是为了提高收敛速度,其最终目的是防止过拟合.在损失函数中,weight decay是放在正则项(regularizat ...
- 一个简单的java jdbc案例
有些时候,配置一个spring+mybatis框架,然后写xml,dao ,service显得特别繁琐. 如果我们只是想查一下数据库,不考虑连接复用也不考虑动态sql,可以用原生的jdbc来实现,方便 ...
- C# 各种类型的转换
/// <summary> /// 一些常用的方法 /// 1.一些高效的转换方法 /// </summary> public class Util { #region Obj ...
- 你竟然在公钥中下毒!——如何在RSA公钥中添加后门
原文:http://www.hackdig.com/?01/hack-17893.htm 分享到: 当我知道它是如何运行时,我惊得下巴都掉了.这是一个非常简单的手法,但这篇文章会颠覆你之前对RSA的看 ...
- JS调用百度地图API标记地点
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- Linux学习笔记:mkdir创建文件夹
文件夹,即目录,在linux中使用mkdir创建. 语法:mkdir dir_name 通过 mkdir 命令可以实现在指定位置创建以 dir_name(指定的文件名)命名的文件夹或目录.要创建文件夹 ...
- 【TensorFlow】Python解析xml文件
最近在项目中使用TensorFlow训练目标检测模型,在制作自己的数据集时使用了labelimg软件对图片进行标注,产生了VOC格式的数据,但标注生成的xml文件标签值难免会产生个别错误造成程序无法跑 ...
- Spring Boot使用JavaMailSender发送邮件
http://www.cnblogs.com/wxc-xiaohuang/p/9532631.html https://blog.csdn.net/icannotdebug/article/detai ...
- 【转】Android开启网络调试的方法
方法是偶然看到的: Android 终端adbd服务需要开启5555号端口来建立于adb的连接,如果未开启5555端口,则不能通过网络调试 查看是否可以网络调试: # netstat Android ...