bzoj2648&2716 SJY摆棋子
原题地址:
http://www.lydsy.com/JudgeOnline/problem.php?id=2648
http://www.lydsy.com/JudgeOnline/problem.php?id=2716
题意:
在一个棋盘上,有N个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) 。现在给出N<=500000个初始棋子。和M<=500000个操作。对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离。同一个格子可能有多个棋子。
数据范围
kdtree可以过。
题解:
裸的Kd-Tree。
像平衡树一样的插入。
我没有重构。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1000006;
int n,m,cur,tail=0,ans,root;
struct node
{
int ls,rs,d[2],mx[2],mn[2];
}tr[N],t;
bool cmp(const node &A,const node &B){return A.d[cur]<B.d[cur];}
void update(int nd)
{
int ls=tr[nd].ls; int rs=tr[nd].rs;
if(ls)
{
tr[nd].mx[0]=max(tr[nd].mx[0],tr[ls].mx[0]);
tr[nd].mn[0]=min(tr[nd].mn[0],tr[ls].mn[0]);
tr[nd].mx[1]=max(tr[nd].mx[1],tr[ls].mx[1]);
tr[nd].mn[1]=min(tr[nd].mn[1],tr[ls].mn[1]);
}
if(rs)
{
tr[nd].mx[0]=max(tr[nd].mx[0],tr[rs].mx[0]);
tr[nd].mn[0]=min(tr[nd].mn[0],tr[rs].mn[0]);
tr[nd].mx[1]=max(tr[nd].mx[1],tr[rs].mx[1]);
tr[nd].mn[1]=min(tr[nd].mn[1],tr[rs].mn[1]);
}
}
void build(int &nd,int lf,int rg,int now)
{
int mid=(lf+rg)>>1; nd=mid; cur=now;
nth_element(tr+lf,tr+mid,tr+rg+1,cmp);
tr[nd].mx[0]=tr[nd].mn[0]=tr[nd].d[0];
tr[nd].mx[1]=tr[nd].mn[1]=tr[nd].d[1];
if(lf<mid) build(tr[nd].ls,lf,mid-1,now^1);
if(rg>mid) build(tr[nd].rs,mid+1,rg,now^1);
update(nd);
}
void insert(int nd,int now)
{
cur=now;
if(cmp(t,tr[nd]))
{
if(tr[nd].ls) insert(tr[nd].ls,now^1);
else {tr[nd].ls=++tail; tr[tail]=t;}
}
else
{
if(tr[nd].rs) insert(tr[nd].rs,now^1);
else { tr[nd].rs=++tail; tr[tail]=t;}
}
update(nd);
}
int abs(int x){return x<0?-x:x;}
int dis(node A,node B) {return abs(A.d[0]-B.d[0])+abs(A.d[1]-B.d[1]);}
int cal(node &x)
{
int ret=0;
for(int i=0;i<2;i++)
{
if(t.d[i]>x.mx[i]) ret+=t.d[i]-x.mx[i];
if(t.d[i]<x.mn[i]) ret+=x.mn[i]-t.d[i];
}
return ret;
}
void query(int nd)
{
ans=min(ans,dis(tr[nd],t)); int dl,dr;
if(tr[nd].ls) dl=cal(tr[tr[nd].ls]); else dl=inf;
if(tr[nd].rs) dr=cal(tr[tr[nd].rs]); else dr=inf;
if(dl<dr)
{
if(dl<ans) query(tr[nd].ls);
if(dr<ans) query(tr[nd].rs);
}
else
{
if(dr<ans) query(tr[nd].rs);
if(dl<ans) query(tr[nd].ls);
}
}
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]);
build(root,1,n,0); tail=n;
while(m--)
{
int opt; scanf("%d%d%d",&opt,&t.d[0],&t.d[1]);
if(opt==1)
{
for(int i=0;i<2;i++) t.mx[i]=t.mn[i]=t.d[i];
insert(root,0);
}
else {ans=inf; query(root); printf("%d\n",ans);}
}
return 0;
}