您的位置:首页 > 其它

bzoj 2648: SJY摆棋子 (KD-tree)

2016-12-27 08:24 387 查看

2648: SJY摆棋子

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 3152  Solved: 1078

[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

鸣谢 孙嘉裕

[Submit][Status][Discuss]

题解:KD-tree

KD-tree模板题

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 1000003
#define inf 2139062143
using namespace std;
struct data
{
int d[2],mx[2],mn[2],l,r;
}tr
;
int n,m,cmpd,x,y,opt,ans,root;
void update(int now)
{
int l=tr[now].l; int r=tr[now].r;
if (l) {
tr[now].mx[0]=max(tr[now].mx[0],tr[l].mx[0]);
tr[now].mx[1]=max(tr[now].mx[1],tr[l].mx[1]);
tr[now].mn[1]=min(tr[now].mn[1],tr[l].mn[1]);
tr[now].mn[0]=min(tr[now].mn[0],tr[l].mn[0]);
}
if (r) {
tr[now].mx[0]=max(tr[now].mx[0],tr[r].mx[0]);
tr[now].mx[1]=max(tr[now].mx[1],tr[r].mx[1]);
tr[now].mn[1]=min(tr[now].mn[1],tr[r].mn[1]);
tr[now].mn[0]=min(tr[now].mn[0],tr[r].mn[0]);
}
}
int cmp(data a,data b)
{
return a.d[cmpd]<b.d[cmpd]||a.d[cmpd]==b.d[cmpd]&&a.d[!cmpd]<b.d[!cmpd];
}
int build(int l,int r,int d)
{
cmpd=d;
int mid=(l+r)/2;
nth_element(tr+l,tr+mid,tr+r+1,cmp);
tr[mid].mx[0]=tr[mid].mn[0]=tr[mid].d[0];
tr[mid].mx[1]=tr[mid].mn[1]=tr[mid].d[1];
if (l!=mid) tr[mid].l=build(l,mid-1,d^1);
if (r!=mid) tr[mid].r=build(mid+1,r,d^1);
update(mid);
return mid;
}
void insert(int now)
{
int p=root; int d=0;
while (true) {
tr[p].mx[0]=max(tr[p].mx[0],tr[now].mx[0]);
tr[p].mx[1]=max(tr[p].mx[1],tr[now].mx[1]);
tr[p].mn[1]=min(tr[p].mn[1],tr[now].mn[1]);
tr[p].mn[0]=min(tr[p].mn[0],tr[now].mn[0]);
if (tr[now].d[d]>=tr[p].d[d])
{
if (!tr[p].r) {
tr[p].r=now; return;
}else p=tr[p].r;
}
else {
if (!tr[p].l) {
tr[p].l=now; return;
}
else p=tr[p].l;
}
d^=1;
}
}
int dist(int now,int x,int y)
{
int dis=0;
if (x<tr[now].mn[0]) dis+=tr[now].mn[0]-x;
if (x>tr[now].mx[0]) dis+=x-tr[now].mx[0];
if (y<tr[now].mn[1]) dis+=tr[now].mn[1]-y;
if (y>tr[now].mx[1]) dis+=y-tr[now].mx[1];
return dis;
}
void query(int now)
{
int dl,dr,d0;
d0=abs(tr[now].d[0]-x)+abs(tr[now].d[1]-y);
ans=min(ans,d0);
if (tr[now].l) dl=dist(tr[now].l,x,y);
else dl=inf;
if (tr[now].r) dr=dist(tr[now].r,x,y);
else dr=inf;
if (dl<dr) {
if (dl<ans) query(tr[now].l);
if (dr<ans) query(tr[now].r);
}
else {
if (dr<ans) query(tr[now].r);
if (dl<ans) query(tr[now].l);
}
}
int main()
{
freopen("a.in","r",stdin);
//freopen("my.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d%d",&tr[i].d[0],&tr[i].d[1]);
root=build(1,n,0);
for (int i=1;i<=m;i++) {
scanf("%d%d%d",&opt,&x,&y);
if (opt==1) {
++n;
tr
.mx[0]=tr
.mn[0]=tr
.d[0]=x;
tr
.mx[1]=tr
.mn[1]=tr
.d[1]=y;
insert(n);
}
else {
ans=inf;
query(root);
printf("%d\n",ans);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: