BZOJ 2648 SJY摆棋子 K-Dimensional-Tree

题目大意:给定平面上的n个点,定义距离为曼哈顿距离,支持下列操作:

1.插入一个点

2.查询离一个点最近的点的距离

Hint说KDTree【可以】过,那么不写KDT还能写啥= =

我的CDQ分治可是T掉了啊= =

记住KDT发生TLE事件的时候不一定是常数问题 有可能写挂了= =(这不和莫队一样么233

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 500500
#define INF 0x3f3f3f3f
using namespace std;
struct Point{
	int x,y;
	friend istream& operator >> (istream &_,Point &p)
	{
		scanf("%d%d",&p.x,&p.y);
		return _;
	}
	friend int Distance(const Point &p1,const Point &p2)
	{
		return abs(p1.x-p2.x) + abs(p1.y-p2.y) ;
	}
}points[M];
int n,m;
bool Compare_x(const Point &p1,const Point &p2)
{
	return p1.x < p2.x ;
}
bool Compare_y(const Point &p1,const Point &p2)
{
	return p1.y < p2.y ;
}
namespace K_Dimensional_Tree{
	struct abcd{
		abcd *ls,*rs;
		Point p;
		int x1,y1,x2,y2;
		abcd() {}
		abcd(const Point &_):p(_)
		{
			ls=rs=0x0;
			x1=x2=p.x;
			y1=y2=p.y;
		}
		void Push_Up(abcd *x)
		{
			x1=min(x1,x->x1);
			y1=min(y1,x->y1);
			x2=max(x2,x->x2);
			y2=max(y2,x->y2);
		}
		int Min_Distance(const Point &p)
		{
			int re=0;
			if(p.x<x1) re+=x1-p.x;
			if(p.x>x2) re+=p.x-x2;
			if(p.y<y1) re+=y1-p.y;
			if(p.y>y2) re+=p.y-y2;
			return re;
		}
		/*
		int Max_Distance(const Point &p)
		{
			int re=0;
			re+=max(p.x-x1,x2-p.x);
			re+=max(p.y-y1,y2-p.y);
			return re;
		}
		*/
	}mempool[M],*C=mempool,*root;
	void Build_Tree(abcd *&x,int l,int r,bool flag)
	{
		if(l>r)
			return ;
		int mid=l+r>>1;
		nth_element(points+l,points+mid,points+r+1,flag?Compare_y:Compare_x);
		x=new abcd(points[mid]);
		Build_Tree(x->ls,l,mid-1,flag^1);
		Build_Tree(x->rs,mid+1,r,flag^1);
		if(x->ls) x->Push_Up(x->ls);
		if(x->rs) x->Push_Up(x->rs);
	}
	void Insert(abcd *&x,const Point &p,bool flag)
	{
		if(!x)
		{
			x=new abcd(p);
			return ;
		}
		if( (flag?Compare_y:Compare_x)(p,x->p) )
		{
			Insert(x->ls,p,flag^1);
			x->Push_Up(x->ls);
		}
		else
		{
			Insert(x->rs,p,flag^1);
			x->Push_Up(x->rs);
		}
	}
	void Get_Min(abcd *x,const Point &p,int &ans)
	{
		ans=min(ans,Distance(x->p,p));
		int l_dis=x->ls?x->ls->Min_Distance(p):INF;
		int r_dis=x->rs?x->rs->Min_Distance(p):INF;
		if(l_dis<r_dis)
		{
			if( x->ls && l_dis<ans )
				Get_Min(x->ls,p,ans);
			if( x->rs && r_dis<ans )
				Get_Min(x->rs,p,ans);
		}
		else
		{
			if( x->rs && r_dis<ans )
				Get_Min(x->rs,p,ans);
			if( x->ls && l_dis<ans )
				Get_Min(x->ls,p,ans);
		}
	}
}
int main()
{
	using namespace K_Dimensional_Tree;
	int i,o;
	Point p;
	cin>>n>>m;
	for(i=1;i<=n;i++)
		cin>>points[i];
	Build_Tree(root,1,n,0);
	for(i=1;i<=m;i++)
	{
		scanf("%d",&o);cin>>p;
		if(o==1)
			Insert(root,p,0);
		else
		{
			int ans=INF;
			Get_Min(root,p,ans);
			printf("%d\n",ans);
		}
	}
	return 0;
}
时间: 2024-10-09 19:08:30

BZOJ 2648 SJY摆棋子 K-Dimensional-Tree的相关文章

BZOJ 2648(SJY摆棋子-KD_Tree)

2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 1180  Solved: 391 [Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=5000

BZOJ 2648: SJY摆棋子(K-D Tree)

Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 6051  Solved: 2113[Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000个初始棋子.和M<=5

BZOJ 2648 SJY摆棋子 / 2716 Violet 3 天使玩偶 K-D树

题目大意:平面上有一些点,问一个点周围离它最近的点的曼哈顿距离是多少.支持动态加点. 思路:CDQ分治可以离线解决,但是SJY是卡CDQ的,天使玩偶可以过.毕竟K-D树的O(sqrt(n))的时间复杂度摆在那. K-D树理解起来其实不难,有k个维度的时候,每一层按照一个维度排序,取出按照这个维度排序的中位数,当作这个块的根,然后将这个块分开.还有一个比较重要的东西就是估价函数,这个函数根据不同的题可能不同.股价函数的主要用途就是对搜索进行剪枝,如果估价函数就已经大于当前的最优答案了,那就不用搜这

BZOJ 2648: SJY摆棋子

Descrption 平面求最近点...\(n\leqslant 5\times 10^5\) Solution KD-Tree. 双倍经验..BZOJ 2716: [Violet 3]天使玩偶 Code /************************************************************** Problem: 2648 User: BeiYu Language: C++ Result: Accepted Time:13864 ms Memory:32560

bzoj 2648: SJY摆棋子&amp;&amp;2716: [Violet 3]天使玩偶 --kdtree

Time Limit: 20 Sec  Memory Limit: 128 MB Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000个初始棋子.和M<=500000个操作.对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离.同一个格子可能有多个棋子

bzoj 2648 SJY摆棋子——KDtree

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2648 第一道KDtree! 学习资料:https://blog.csdn.net/zhl30041839/article/details/9277807 https://www.cnblogs.com/galaxies/p/kdtree.html 这道题的代码是学习(抄)的这里的:https://blog.csdn.net/lych_cys/article/details/50809141

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 in

bzoj 2648 SJY摆棋子 cdq分治+树状数组

题面 题目传送门 解法 同bzoj2716 自己cdq写的还是丑啊,别人A掉了我T飞了 代码 #include <bits/stdc++.h> #define inf 1 << 30 #define N 1000010 using namespace std; template <typename node> void chkmax(node &x, node y) {x = max(x, y);} template <typename node>

【BZOJ】2648: SJY摆棋子 &amp; 2716: [Violet 3]天使玩偶(kdtree)

http://www.lydsy.com/JudgeOnline/problem.php?id=2716 http://www.lydsy.com/JudgeOnline/problem.php?id=2648 双倍经验题... kdtree裸题吧.....今天学了下kdtree...感觉挺简单的.... 其实就是对几何图形进行剖分建树,而特殊在于,x和y轴轮流剖....这样可以提供很好的性质以便于查找... (一开始脑补了个treap代替kdtree.....显然我脑残了....写到一半发现这