[bzoj2648]SJY摆棋子【kd-tree】

【题目描述】

2648: SJY摆棋子

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 5319  Solved: 1861
[Submit][Status][Discuss]

Description

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

Input

第一行两个数 N M
以后M行,每行3个数 t x y
如果t=1 那么放下一个黑色棋子
如果t=2 那么放下一个白色棋子

Output

对于每个T=2 输出一个最小距离
 

Sample Input

2 3
1 1
2 3
2 1 2
1 3 3
2 4 2

Sample Output


1
2

HINT

 

kdtree可以过

Source

【题解】

 大力KD-tree,数据很水,怎么建树都行。

 tips:query时,若查询点到当前区间四端的距离>ans,则直接退出

复杂度我不会证

/* --------------
    user Vanisher
    problem bzoj-2648  KD-tree
----------------*/
# include <bits/stdc++.h>
# define	N		1000100
# define 	inf 	2e9
using namespace std;
int read(){
	int tmp=0, fh=1; char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
	while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
	return tmp*fh;
}
struct point{int x,y;}p[N],now;
struct kd_tree{
	point num;
	int pl,pr,tag,lx,ly,rx,ry;
}T[N];
int place,ans,n,m,rt,opt;
bool cmpx(point x, point y){return x.x<y.x;}
bool cmpy(point x, point y){return x.y<y.y;}
void change(int now){
	T[now].rx=max(T[now].rx,max(T[T[now].pl].rx,T[T[now].pr].rx));
	T[now].ry=max(T[now].ry,max(T[T[now].pl].ry,T[T[now].pr].ry));
	T[now].lx=min(T[now].lx,min(T[T[now].pl].lx,T[T[now].pr].lx));
	T[now].ly=min(T[now].ly,min(T[T[now].pl].ly,T[T[now].pr].ly));
}
int build(int l, int r, int tag){
	if (l>r) return 0;
	int now=++place; 
	T[now].tag=tag;
	int mid=(l+r)/2;
	if (tag==0) nth_element(p+l,p+mid,p+r+1,cmpx);
			else nth_element(p+l,p+mid,p+r+1,cmpy);
	T[now].num=p[mid];
	T[now].rx=T[now].lx=p[mid].x; T[now].ry=T[now].ly=p[mid].y;
	T[now].pl=build(l,mid-1,tag^1); T[now].pr=build(mid+1,r,tag^1);
	change(now);
	return now;
}
void extend(int rt, point x){
	int las,now=rt;
	while (now!=0){
		T[now].rx=max(T[now].rx,x.x); T[now].lx=min(T[now].lx,x.x);
		T[now].ry=max(T[now].ry,x.y); T[now].ly=min(T[now].ly,x.y);
		las=now;
		if (T[now].tag==0)
			if (T[now].num.x>=x.x)
				now=T[now].pl; else now=T[now].pr;
			else if (T[now].num.y>=x.y)
				now=T[now].pl; else now=T[now].pr;
	}
	now=++place; T[now].num=x; T[now].tag=T[las].tag^1;
	T[now].rx=T[now].lx=x.x; T[now].ry=T[now].ly=x.y;
	if (T[las].tag==0)
		if (T[las].num.x>=x.x)
			T[las].pl=now; else T[las].pr=now;
		else if (T[las].num.y>=x.y)
			T[las].pl=now; else T[las].pr=now;
}
int dist(int p){
     int dis=0;
     if(now.x<T[p].lx) dis+=T[p].lx-now.x;
     if(now.x>T[p].rx) dis+=now.x-T[p].rx;
     if(now.y<T[p].ly) dis+=T[p].ly-now.y;
     if(now.y>T[p].ry) dis+=now.y-T[p].ry;
     return dis;
}
void query(int p){
    int dl,dr,d0;
    d0=abs(T[p].num.x-now.x)+abs(T[p].num.y-now.y);
    if(d0<ans) ans=d0;
    if(T[p].pl) dl=dist(T[p].pl); else dl=inf;
    if(T[p].pr) dr=dist(T[p].pr); else dr=inf;
    if(dl<dr) {
		if(dl<ans) query(T[p].pl);
     	if(dr<ans) query(T[p].pr);
    }
    else{
    	if(dr<ans) query(T[p].pr);
     	if(dl<ans) query(T[p].pl);
    }
}
int main(){
	n=read(); m=read();
	for (int i=1; i<=n; i++)
		p[i].x=read(), p[i].y=read();
	T[0].lx=T[0].ly=inf; T[0].rx=T[0].ry=-inf; 
	rt=build(1,n,0);
	for (int i=1; i<=m; i++){
		opt=read(); now.x=read(); now.y=read();
		if (opt==1) extend(rt,now);
			else {
				ans=inf; query(rt);
				printf("%d\n",ans);
			}
	}
	return 0;
}




posted @ 2018-01-21 13:06  Vanisher  阅读(128)  评论(0编辑  收藏  举报