2648: SJY摆棋子/2716: [Violet 3]天使玩偶 K-D tree

来源:互联网 发布:淘宝优惠卷 编辑:程序博客网 时间:2024/05/22 04:57

K-D tree裸题,求平面最小曼哈顿距离。
每次分治的时候看看点是否处于左子树和右子树的矩形内,如果在矩形内就递归处理,否则计算点和矩形的最小距离,如果<ans

#include<iostream>#include<cstdio>#include<algorithm>#define N 1000005#define inf 1000000007using namespace std;struct node{    int d[2],mn[2],mx[2];};node tree[N];int ls[N],rs[N];int n,m,D,root,ans;int I[2];inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}inline bool operator<(node a,node b){    return a.d[D]==b.d[D]?a.d[D^1]<b.d[D^1]:a.d[D]<b.d[D];}inline int calc(int k){    return max(tree[k].mn[0]-I[0],0)+max(I[0]-tree[k].mx[0],0)+max(tree[k].mn[1]-I[1],0)+max(I[1]-tree[k].mx[1],0);}inline void pushup(int k){    for (int i=0;i<=1;i++)    {        tree[k].mn[i]=min(tree[k].mn[i],min(tree[ls[k]].mn[i],tree[rs[k]].mn[i]));        tree[k].mx[i]=max(tree[k].mx[i],max(tree[ls[k]].mx[i],tree[rs[k]].mx[i]));    }}void build(int &k,int l,int r,int dir){    int mid=l+r>>1; k=mid; D=dir;    nth_element(tree+l,tree+mid,tree+r+1);    tree[mid].mn[0]=tree[mid].mx[0]=tree[mid].d[0];    tree[mid].mn[1]=tree[mid].mx[1]=tree[mid].d[1];    if (l<mid) build(ls[k],l,mid-1,dir^1);    if (r>mid) build(rs[k],mid+1,r,dir^1);    pushup(k);}void insert(int k,int dir){    if (I[dir]<tree[k].d[dir])    {        if (ls[k]) insert(ls[k],dir^1);        else        {            ls[k]=++n;            tree[n].mn[0]=tree[n].mx[0]=tree[n].d[0]=I[0];            tree[n].mn[1]=tree[n].mx[1]=tree[n].d[1]=I[1];        }    }    else    {        if (rs[k]) insert(rs[k],dir^1);        else        {            rs[k]=++n;            tree[n].mn[0]=tree[n].mx[0]=tree[n].d[0]=I[0];            tree[n].mn[1]=tree[n].mx[1]=tree[n].d[1]=I[1];        }    }    pushup(k);}       void query(int k,int dir){    int d=abs(tree[k].d[0]-I[0])+abs(tree[k].d[1]-I[1]);    int dl=inf,dr=inf;    ans=min(ans,d);    if (ls[k]) dl=calc(ls[k]);    if (rs[k]) dr=calc(rs[k]);    if (dl<dr)    {        if (dl<ans) query(ls[k],dir^1);        if (dr<ans) query(rs[k],dir^1);    }    else    {        if (dr<ans) query(rs[k],dir^1);        if (dl<ans) query(ls[k],dir^1);    }}int main(){    tree[0].mn[0]=tree[0].mn[1]=inf;    tree[0].mx[0]=tree[0].mx[1]=-inf;    n=read(); m=read();    for (int i=1;i<=n;i++)        tree[i].d[0]=read(),tree[i].d[1]=read();    build(root,1,n,1);    for (int i=1;i<=m;i++)    {        int opt=read();        I[0]=read(); I[1]=read();        if (opt==1) insert(root,1);         else         {            ans=inf;            query(root,1);            printf("%d\n",ans);        }    }    return 0;}
0 0
原创粉丝点击