BZOJ 2648: SJY摆棋子 kdtree

2648: SJY摆棋子

题目连接:

http://www.lydsy.com/JudgeOnline/problem.php?id=2648

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裸题

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000005;
#define INF 1000000000
struct arr{
    int d[2],min[2],max[2],l,r;
};
int D,root,x,y,ans,n,m,tot,op;;
inline int cmp(arr a,arr b)
{
    return a.d[D]<b.d[D]||a.d[D]==b.d[D]&&a.d[D^1]<b.d[D^1];
}
arr a[maxn];

inline void up(int k,int s)
{
    a[k].min[0]=min(a[k].min[0],a[s].min[0]);
    a[k].max[0]=max(a[k].max[0],a[s].max[0]);
    a[k].min[1]=min(a[k].min[1],a[s].min[1]);
    a[k].max[1]=max(a[k].max[1],a[s].max[1]);
}
int build(int l,int r,int dd)
{
    D=dd;int mid=(l+r)>>1;
    nth_element(a+l+1,a+mid+1,a+r+1,cmp);
    a[mid].min[0]=a[mid].max[0]=a[mid].d[0];
    a[mid].min[1]=a[mid].max[1]=a[mid].d[1];
    if (l!=mid) a[mid].l=build(l,mid-1,dd^1);
    if (mid!=r) a[mid].r=build(mid+1,r,dd^1);
    if (a[mid].l) up(mid,a[mid].l);
    if (a[mid].r) up(mid,a[mid].r);
    return mid;
}
void insert(int k)
{
    int p=root;D=0;
    while (1)
    {
        up(p,k);
        if (a[k].d[D]<=a[p].d[D]){if (!a[p].l) {a[p].l=k;return;} p=a[p].l;}
        else {if (!a[p].r) {a[p].r=k;return;} p=a[p].r;}
        D^=1;
    }
}
int getdis(int k)
{
    int res=0;
    if (x<a[k].min[0]) res+=a[k].min[0]-x;
    if (x>a[k].max[0]) res+=x-a[k].max[0];
    if (y<a[k].min[1]) res+=a[k].min[1]-y;
    if (y>a[k].max[1]) res+=y-a[k].max[1];
    return res;
}
void ask(int k)
{
  int d0=abs(a[k].d[0]-x)+abs(a[k].d[1]-y);
  if (d0<ans) ans=d0;
  int dl=(a[k].l)?getdis(a[k].l):INF;
  int dr=(a[k].r)?getdis(a[k].r):INF;
  if (dl<dr){if (dl<ans) ask(a[k].l);if (dr<ans) ask(a[k].r);}
  else {if (dr<ans) ask(a[k].r);if (dl<ans) ask(a[k].l);}
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&a[i].d[0],&a[i].d[1]);
    }
    if(n)root = build(1,n,0);
    for(int i=1;i<=m;i++){
        scanf("%d",&op);
        if(op==1){
            n++;
            scanf("%d%d",&a[n].d[0],&a[n].d[1]);
            a[n].min[0]=a[n].max[0]=a[n].d[0];
            a[n].min[1]=a[n].max[1]=a[n].d[1];
            insert(n);
        }else if(op==2){
            ans=2000000000;
            scanf("%d%d",&x,&y);
            ask(root);
            printf("%d\n",ans);
        }
    }
}



你可能感兴趣的:(BZOJ 2648: SJY摆棋子 kdtree)