BZOJ2648/2716【KD tree】

2648这题卡常数.加了inline.开了内存池.卡时过掉了.

/* I will wait for you */

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<vector>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>

typedef long long LL;
typedef unsigned long long ULL;

using namespace std;

const int maxn=400010;
const int maxm=210;
const int maxs=26;
const int INF=1<<28;
const int P=1000000007;
const double error=1e-9;

struct node
{
	int x,y,mix,max,miy,may;
	node* son[2];
}su[maxn];

int cnt=0,ans;

inline void init(node* &a,int x,int y)
{
	a->x=a->mix=a->max=x;
	a->y=a->miy=a->may=y;
	a->son[0]=a->son[1]=0;
}

inline void maintain(node* o)
{
	o->mix=o->max=o->x;
	o->miy=o->may=o->y;
	for(int i=0;i<2;i++) if(o->son[i])
	{
		o->mix=min(o->mix,o->son[i]->mix);
		o->max=max(o->max,o->son[i]->max);
		o->miy=min(o->miy,o->son[i]->miy);
		o->may=max(o->may,o->son[i]->may);
	}
}

inline void insert(node* &o,int x,int y,int d)
{
	if(!o) o=&su[cnt++],init(o,x,y);
	else 
	{
		if(d==0) insert(o->son[x>o->x],x,y,d^1);
		if(d==1) insert(o->son[y>o->y],x,y,d^1);
		maintain(o);
	}
}

inline int dis(node* o,int x,int y)
{
	int ans=0;
	if(x<o->mix) ans+=o->mix-x;
	if(x>o->max) ans+=x-o->max;
	if(y<o->miy) ans+=o->miy-y;
	if(y>o->may) ans+=y-o->may;
	return ans;
}

inline int find(node* o,int x,int y)
{
	int dn=abs(x-o->x)+abs(y-o->y);
	ans=min(ans,dn);
	int dl=o->son[0]?dis(o->son[0],x,y):INF;
	int dr=o->son[1]?dis(o->son[1],x,y):INF;
	
	if(dl<=dr) 
	{
		if(dl<ans) find(o->son[0],x,y);
		if(dr<ans) find(o->son[1],x,y);
	}
	if(dr<dl)
	{
		if(dr<ans) find(o->son[1],x,y);
		if(dl<ans) find(o->son[0],x,y);
	}
}

int main()
{
	int n,m;node* root=0;
	scanf("%d%d",&n,&m);
	for(int i=0,x,y;i<n;i++) scanf("%d%d",&x,&y),insert(root,x,y,0);
	
	while(m--)
	{
		int t,x,y;scanf("%d%d%d",&t,&x,&y);
		if(t==1) insert(root,x,y,0);
		if(t==2) ans=INF,find(root,x,y),printf("%d\n",ans);
	}
	
    return 0;
}

发现最开始给定的节点不用逐一插入.可以直接建树.

/* I will wait for you */

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<vector>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>

typedef long long LL;
typedef unsigned long long ULL;

using namespace std;

const int maxn=2000010;
const int maxm=210;
const int maxs=26;
const int INF=1<<28;
const int P=1000000007;
const double error=1e-9;

struct node
{
	int x,y,mix,max,miy,may;
	node* son[2];
}su[maxn];

struct point{ int x,y; }e[maxn];

bool cmpx(point a,point b)
{
	return a.x<b.x;
}

bool cmpy(point a,point b)
{
	return a.y<b.y;
}

int cnt=0,ans;

inline void init(node* &a,int x,int y)
{
	a->x=a->mix=a->max=x;
	a->y=a->miy=a->may=y;
	a->son[0]=a->son[1]=0;
}

inline void maintain(node* o)
{
	o->mix=o->max=o->x;
	o->miy=o->may=o->y;
	for(int i=0;i<2;i++) if(o->son[i])
	{
		o->mix=min(o->mix,o->son[i]->mix);
		o->max=max(o->max,o->son[i]->max);
		o->miy=min(o->miy,o->son[i]->miy);
		o->may=max(o->may,o->son[i]->may);
	}
}

inline node* build(int l,int r,int d)
{
	int mid=(l+r)>>1;
	if(d==0) nth_element(e+l,e+mid,e+r+1,cmpx);
	if(d==1) nth_element(e+l,e+mid,e+r+1,cmpy);
	node* o=&su[cnt++];init(o,e[mid].x,e[mid].y);
	
	if(l!=mid) o->son[0]=build(l,mid-1,d^1);
	if(r!=mid) o->son[1]=build(mid+1,r,d^1);
	maintain(o);return o;
}

inline void insert(node* &o,int x,int y,int d)
{
	if(!o) o=&su[cnt++],init(o,x,y);
	else 
	{
		if(d==0) insert(o->son[x>o->x],x,y,d^1);
		if(d==1) insert(o->son[y>o->y],x,y,d^1);
		maintain(o);
	}
}

inline int dis(node* o,int x,int y)
{
	int ans=0;
	if(x<o->mix) ans+=o->mix-x;
	if(x>o->max) ans+=x-o->max;
	if(y<o->miy) ans+=o->miy-y;
	if(y>o->may) ans+=y-o->may;
	return ans;
}

inline int find(node* o,int x,int y)
{
	int dn=abs(x-o->x)+abs(y-o->y);
	ans=min(ans,dn);
	int dl=o->son[0]?dis(o->son[0],x,y):INF;
	int dr=o->son[1]?dis(o->son[1],x,y):INF;
	
	if(dl<=dr) 
	{
		if(dl<ans) find(o->son[0],x,y);
		if(dr<ans) find(o->son[1],x,y);
	}
	if(dr<dl)
	{
		if(dr<ans) find(o->son[1],x,y);
		if(dl<ans) find(o->son[0],x,y);
	}
}

int main()
{
	int n,m;scanf("%d%d",&n,&m);
	for(int i=1,x,y;i<=n;i++) scanf("%d%d",&e[i].x,&e[i].y);
	node* root=build(1,n,0);
	
	while(m--)
	{
		int t,x,y;scanf("%d%d%d",&t,&x,&y);
		if(t==1) insert(root,x,y,0);
		if(t==2) ans=INF,find(root,x,y),printf("%d\n",ans);
	}
	
<span style="white-space:pre">	</span>return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值