1941: [Sdoi2010]Hide and Seek K-D tree

来源:互联网 发布:qq教程网php源码 编辑:程序博客网 时间:2024/05/12 02:09

K-D tree裸题。。据说yzy神犇写了大力讨论+动态加点线段树。。膜膜膜

#include<iostream>#include<cstdio>#include<algorithm>#define inf 1000000007#define N 500005using namespace std;struct node {    int d[2],mn[2],mx[2];};node tree[N];int ls[N],rs[N];int n,D,root,ans,ans1,ans2,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 void pushup(int k){    for (int i=0;i<2;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]));    }}inline int dis_min(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 int dis_max(int k){    return max(abs(tree[k].mn[0]-I[0]),abs(tree[k].mx[0]-I[0]))+max(abs(tree[k].mx[1]-I[1]),abs(tree[k].mn[1]-I[1]));}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[k].mn[0]=tree[k].mx[0]=tree[k].d[0];    tree[k].mn[1]=tree[k].mx[1]=tree[k].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 query_max(int k){    int d=abs(tree[k].d[0]-I[0])+abs(tree[k].d[1]-I[1]);    if (d) ans2=max(ans2,d);    int dl=-inf,dr=-inf;    if (ls[k]) dl=dis_max(ls[k]);    if (rs[k]) dr=dis_max(rs[k]);    if (dl>dr)    {        if (dl>ans2) query_max(ls[k]);        if (dr>ans2) query_max(rs[k]);    }    else    {        if (dr>ans2) query_max(rs[k]);        if (dl>ans2) query_max(ls[k]);    }}void query_min(int k){    int d=abs(tree[k].d[0]-I[0])+abs(tree[k].d[1]-I[1]);    if (d) ans1=min(ans1,d);    int dl=inf,dr=inf;    if (ls[k]) dl=dis_min(ls[k]);    if (rs[k]) dr=dis_min(rs[k]);    if (dl<dr)    {        if (dl<ans1) query_min(ls[k]);        if (dr<ans1) query_min(rs[k]);    }    else    {        if (dr<ans1) query_min(rs[k]);        if (dl<ans1) query_min(ls[k]);    }}   int main(){    tree[0].mx[0]=tree[0].mx[1]=-inf;    tree[0].mn[0]=tree[0].mn[1]=inf;    n=read();    for (int i=1;i<=n;i++)        tree[i].d[0]=read(),tree[i].d[1]=read();    build(root,1,n,1);    ans=inf;    for (int i=1;i<=n;i++)    {        ans1=inf; ans2=-inf;        I[0]=tree[i].d[0]; I[1]=tree[i].d[1];        query_min(root); query_max(root);        ans=min(ans,ans2-ans1);    }    cout << ans << endl;    return 0;}
0 0