[BZOJ2648]SJY摆棋子(kd-tree)

来源:互联网 发布:don t starve mac 编辑:程序博客网 时间:2024/04/29 04:36

题目描述

传送门

题解

和天使玩偶那道题一样,不过这题才20s,那道题我跑了将近60s
不过就是一道kd-tree裸题= =

代码

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define N 1000005#define inf 2147483647struct data{int d[2],mx[2],mn[2],l,r;}tr[N];int n,m,cmpd,x,y,opt,ans,root;void update(int now){    int l=tr[now].l,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[0]=min(tr[now].mn[0],tr[l].mn[0]);        tr[now].mn[1]=min(tr[now].mn[1],tr[l].mn[1]);    }    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[0]=min(tr[now].mn[0],tr[r].mn[0]);        tr[now].mn[1]=min(tr[now].mn[1],tr[r].mn[1]);    }}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){    int mid=(l+r)>>1;    cmpd=d;    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 x){    int now=root,d=0;    while (1)    {        tr[now].mx[0]=max(tr[now].mx[0],tr[x].mx[0]);        tr[now].mx[1]=max(tr[now].mx[1],tr[x].mx[1]);        tr[now].mn[0]=min(tr[now].mn[0],tr[x].mn[0]);        tr[now].mn[1]=min(tr[now].mn[1],tr[x].mn[1]);        if (tr[x].d[d]>=tr[now].d[d])        {            if (!tr[now].r) {tr[now].r=x;return;}            else now=tr[now].r;        }        else        {            if (!tr[now].l) {tr[now].l=x;return;}            else now=tr[now].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;    int 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(){    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[n].mx[0]=tr[n].mn[0]=tr[n].d[0]=x;            tr[n].mx[1]=tr[n].mn[1]=tr[n].d[1]=y;            insert(n);        }        else        {            ans=inf;            query(root);            printf("%d\n",ans);        }    }}
0 0
原创粉丝点击