kd-tree

#include<bits/stdc++.h>
#define alpha (1.130/2)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

const int DEM=2;
const int maxn=1000010;
int n,m,now,ans,root,points;
queue<int>Q;
struct point
{
    int x[DEM]; 
    bool operator < (const point X) const {return x[now]<X.x[now];}
}one[maxn];
struct node
{
    int l,r;
    int sze;
    int minn[DEM];
    int maxx[DEM];
    point data;
}tree[maxn];
int dist(point A,point B) 
{
	int ans=0;
	for(int i=0;i<DEM;i++)
	ans+=abs(A.x[i]-B.x[i]);
	return ans;
}
int get_dist(point A,int pos) 
{
	int ret=0; 
	for(int i=0;i<DEM;i++) 
	ret+=max(0,A.x[i]-tree[pos].maxx[i])+max(0,tree[pos].minn[i]-A.x[i]); 
	return ret;
}
int New()
{
    if(!Q.empty()) 
	{
		static int tmp; 
		tmp=Q.front(); 
		Q.pop(); 
		return tmp;
	}
    else return ++points;
}
void update(int pos)
{
    for(int i=0;i<DEM;i++)
    {
        tree[pos].maxx[i]=tree[pos].minn[i]=tree[pos].data.x[i];
        if(tree[pos].l) 
		{
			tree[pos].minn[i]=min(tree[pos].minn[i],tree[tree[pos].l].minn[i]);
			tree[pos].maxx[i]=max(tree[pos].maxx[i],tree[tree[pos].l].maxx[i]);
		}
        if(tree[pos].r) 
		{
			tree[pos].minn[i]=min(tree[pos].minn[i],tree[tree[pos].r].minn[i]);
        	tree[pos].maxx[i]=max(tree[pos].maxx[i],tree[tree[pos].r].maxx[i]);
        }
    }
    tree[pos].sze=tree[tree[pos].l].sze+tree[tree[pos].r].sze+1;
}
void rev(int pos,int num)
{
    if(tree[pos].l) rev(tree[pos].l,num);
    one[tree[tree[pos].l].sze+num+1]=tree[pos].data; Q.push(pos);
    if(tree[pos].r) rev(tree[pos].r,tree[tree[pos].l].sze+num+1);
}
int build(int l,int r,int dem)
{
    if(l>r) return 0;
    int mid=(l+r)>>1,pos=New();
    now=dem; 
	//nth_element(a+l,a+k,a+r),使a这个数组中区间[l,r)内的第k小的元素处在第k个位置上(相对位置)
	nth_element(one+l,one+mid,one+r+1); 
	tree[pos].data=one[mid]; 
    tree[pos].l=build(l,mid-1,dem^1); 
	tree[pos].r=build(mid+1,r,dem^1);
    update(pos); 
	return pos;
}
void check(int& pos,int dem)
{
    if(tree[pos].sze*alpha<tree[tree[pos].l].sze||tree[pos].sze*alpha<tree[tree[pos].r].sze)
    {
		rev(pos,0); 
		pos=build(1,tree[pos].sze,dem);
	}
}
int insert(int pos,point data,int dem)
{
    if(!pos) 
	{
		pos=New(); 
		tree[pos].l=tree[pos].r=0; 
		tree[pos].data=data; 
		update(pos); 
		return pos;
	}
    if(data.x[dem]<=tree[pos].data.x[dem]) tree[pos].l=insert(tree[pos].l,data,dem^1);
    else tree[pos].r=insert(tree[pos].r,data,dem^1);
    update(pos); 
	check(pos,dem); 
	return pos;
}
void query(int pos,point data)
{
    ans=min(ans,dist(data,tree[pos].data));
    int dist_left=INF,dist_right=INF;
    if(tree[pos].l) dist_left=get_dist(data,tree[pos].l);
    if(tree[pos].r) dist_right=get_dist(data,tree[pos].r);
    if(dist_left<dist_right)
    {
        if(dist_left<ans) query(tree[pos].l,data);
        if(dist_right<ans) query(tree[pos].r,data);
    }
    else 
    {
        if(dist_right<ans) query(tree[pos].r,data);
        if(dist_left<ans) query(tree[pos].l,data);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) 
	scanf("%d%d",&one[i].x[0],&one[i].x[1]);
    root=build(1,n,0);
    int opt,u,v;
    for(int i=1;i<=m;i++)
    {
    	scanf("%d%d%d",&opt,&u,&v);
        if(opt==1) //加点
		{
			root=insert(root,(point){u,v},0);
		}
        else //询问离当前点最近的点
		{
			ans=INF; 
			query(root,(point){u,v}); 
			printf("%d\n",ans);
		}  
    } 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值