您的位置:首页 > 其它

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

2018-01-21 13:05 435 查看
【题目描述】

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
,now;
struct kd_tree{
point num;
int pl,pr,tag,lx,ly,rx,ry;
}T
;
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
4000
=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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: