BZOJ2648: SJY摆棋子

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可以过

 

这个HINT太神仙了。。。

yy一下KD-tree插入操作,顺着访问一遍有孩子是空的就插进去

这样做不是会把树的结构都给破坏掉吗??那就得暴力重构

没重构也擦边卡过美滋滋

//MT_LI
#include<cmath> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; struct KDT{ int lc,rc,d[2],mn[2],mx[2]; }tr[1100000]; void update(int x) { int lc=tr[x].lc,rc=tr[x].rc; if(lc) { tr[x].mn[0]=min(tr[x].mn[0],tr[lc].mn[0]); tr[x].mn[1]=min(tr[x].mn[1],tr[lc].mn[1]); tr[x].mx[0]=max(tr[x].mx[0],tr[lc].mx[0]); tr[x].mx[1]=max(tr[x].mx[1],tr[lc].mx[1]); } if(rc) { tr[x].mn[0]=min(tr[x].mn[0],tr[rc].mn[0]); tr[x].mn[1]=min(tr[x].mn[1],tr[rc].mn[1]); tr[x].mx[0]=max(tr[x].mx[0],tr[rc].mx[0]); tr[x].mx[1]=max(tr[x].mx[1],tr[rc].mx[1]); } } int cmpd; bool cmp(KDT a,KDT b){return a.d[cmpd]<b.d[cmpd] || a.d[cmpd]==b.d[cmpd]&&a.d[cmpd^1]<b.d[cmpd^1];} int bt(int l,int r,int d) { int mid=(l+r)/2,now; now=mid;cmpd=d; nth_element(tr+l,tr+mid,tr+r+1,cmp); tr[now].mx[0]=tr[now].mn[0]=tr[now].d[0]; tr[now].mx[1]=tr[now].mn[1]=tr[now].d[1]; if(l<mid)tr[now].lc=bt(l,mid-1,d^1); if(mid<r)tr[now].rc=bt(mid+1,r,d^1); update(now); return now; } int n,root; int nowx,nowy; int minn; int dismin(int now,int x,int y) { int d=0; if(x<tr[now].mn[0])d+=tr[now].mn[0]-x; if(x>tr[now].mx[0])d+=x-tr[now].mx[0]; if(y<tr[now].mn[1])d+=tr[now].mn[1]-y; if(y>tr[now].mx[1])d+=y-tr[now].mx[1]; return d; } void findmin(int now) { int dl=1<<30,dr=1<<30; int d=abs(tr[now].d[0]-nowx)+abs(tr[now].d[1]-nowy); minn=min(minn,d); if(tr[now].lc)dl=dismin(tr[now].lc,nowx,nowy); if(tr[now].rc)dr=dismin(tr[now].rc,nowx,nowy); if(dl<dr) { if(dl<minn)findmin(tr[now].lc); if(dr<minn)findmin(tr[now].rc); } else { if(dr<minn)findmin(tr[now].rc); if(dl<minn)findmin(tr[now].lc); } } void ins(int now) { int p=root; while(1) { if(tr[p].mx[0]<tr[now].mx[0])tr[p].mx[0]=tr[now].mx[0]; if(tr[p].mx[1]<tr[now].mx[1])tr[p].mx[1]=tr[now].mx[1]; if(tr[p].mn[0]>tr[now].mn[0])tr[p].mn[0]=tr[now].mn[0]; if(tr[p].mn[1]>tr[now].mn[1])tr[p].mn[1]=tr[now].mn[1]; if(tr[now].d[cmpd]<tr[p].d[cmpd]) { if(tr[p].lc==0){tr[p].lc=now;return ;} else p=tr[p].lc; } else { if(tr[p].rc==0){tr[p].rc=now;return ;} else p=tr[p].rc; } cmpd^=1; } } int m; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d%d",&tr[i].d[0],&tr[i].d[1]); root=bt(1,n,0); for(int i=1;i<=m;i++) { int op; scanf("%d",&op); if(op==2) { scanf("%d%d",&nowx,&nowy); minn=1<<30;findmin(root); printf("%d\n",minn); } else { n++; scanf("%d%d",&tr[n].d[0],&tr[n].d[1]); tr[n].mx[0]=tr[n].mn[0]=tr[n].d[0]; tr[n].mx[1]=tr[n].mn[1]=tr[n].d[1]; cmpd=0;ins(n); } } return 0; }

 

posted @ 2018-10-09 16:36  MT_LI  阅读(156)  评论(0编辑  收藏  举报