其他分享
首页 > 其他分享> > bzoj 1941: [Sdoi2010]Hide and Seek

bzoj 1941: [Sdoi2010]Hide and Seek

作者:互联网

KD_tree的估价查询

 

/**************************************************************
    Problem: 1941
    User: lxy8584099
    Language: C++
    Result: Accepted
    Time:2952 ms
    Memory:32080 kb
****************************************************************/
 
/*
 
枚举每个点 找最大最小距离 更新
findmax/min函数只是一个估价函数 
选择最优的先进行递归 可能次优的就不会进入递归了
max里所有维取最大值进行计算距离 返回一个估价值
min里的股价方式有点玄学。。。好象是卡在mx和mn之间的时候越优
估价方式往往决定了KD_tree的查询效率。
*/
#include<cmath>
#include<cstdio>
#include<algorithm>
#define ll long long
#define inf (0x3fffffff)
using namespace std;
const int N=5e5+50;
int n,now,rt,ans;
struct data
{
    int d[2],mx[2],mn[2],lc,rc;
    friend bool operator < (data a,data b)
        {return a.d[now]<b.d[now];}
}dat[N],t[N],p;
void getmax(int&a,int b){if(a<b)a=b;}
void getmin(int&a,int b){if(a>b)a=b;}
void pushup(int x)
{
    for(int i=0;i<2;i++)
    {
        int lc=t[x].lc,rc=t[x].rc;
        t[x].mn[i]=t[x].mx[i]=t[x].d[i];
        if(lc)  getmin(t[x].mn[i],t[lc].mn[i]),
            getmax(t[x].mx[i],t[lc].mx[i]);
        if(rc)  getmin(t[x].mn[i],t[rc].mn[i]),
            getmax(t[x].mx[i],t[rc].mx[i]);
    }
}
int build(int l,int r,int pl)
{
    now=pl; int mid=(l+r)>>1;
    nth_element(dat+l,dat+mid,dat+r+1);
    t[mid]=dat[mid];
    if(l<mid) t[mid].lc=build(l,mid-1,!pl);
    if(r>mid) t[mid].rc=build(mid+1,r,!pl);
    pushup(mid); return mid;
}
int dist(data a,data b)
{
    return abs(a.d[0]-b.d[0])+abs(a.d[1]-b.d[1]);
}
int findmax(data a)
{
    int res=0;
    for(int i=0;i<2;i++)
        res+=max(abs(p.d[i]-a.mx[i]),abs(p.d[i]-a.mn[i]));
    return res;
}
void querymax(int x)
{
    getmax(ans,dist(t[x],p));
    int lc=t[x].lc,rc=t[x].rc;
    int ml=-inf,mr=-inf;
    if(lc) ml=findmax(t[lc]);
    if(rc) mr=findmax(t[rc]);
    if(lc>rc)
    {
        if(ml>ans) querymax(lc);
        if(mr>ans) querymax(rc);
    }
    else
    {
        if(mr>ans) querymax(rc);
        if(ml>ans) querymax(lc);
    }
}
int findmin(data a)
{
    int res=0;
    for(int i=0;i<2;i++)
        res+=max(p.d[i]-a.mx[i],0),
        res+=max(a.mn[i]-p.d[i],0);
    return res;
}
void querymin(int x)
{
    int tmp=dist(t[x],p);
    if(tmp) getmin(ans,tmp);
    int lc=t[x].lc,rc=t[x].rc;
    int ml=inf,mr=inf;
    if(lc) ml=findmin(t[lc]);
    if(rc) mr=findmin(t[rc]);
    if(ml<mr)
    {
        if(ml<ans) querymin(lc);
        if(mr<ans) querymin(rc);
    }
    else
    {
        if(mr<ans) querymin(rc);
        if(ml<ans) querymin(lc);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&dat[i].d[0],&dat[i].d[1]);
    rt=build(1,n,0); int end=inf;
    for(int i=1;i<=n;i++)
    {
        int minn,maxn; p=dat[i];
        ans=-inf; querymax(rt); maxn=ans;
        ans=inf; querymin(rt); minn=ans;
        getmin(end,maxn-minn);
    }
    printf("%d\n",end);
    return 0;
}

 

标签:dat,rc,int,data,1941,mid,Sdoi2010,ans,Seek
来源: https://www.cnblogs.com/lxy8584099/p/10427725.html