[bzoj2648]SJY摆棋子【kd-tree】
【题目描述】
2648: SJY摆棋子
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 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
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; }