【K-D树 求最近最远距离】BZOJ 1941 [Sdoi2010]Hide and Seek

来源:互联网 发布:见过好听的名字 知乎 编辑:程序博客网 时间:2024/05/25 19:57

Problem Description

给你n个点(二维),让你求所有点 到最远点 和最近点 的距离差最小

思路:

自身点不算。
求个距离该点,最近距离。和 距离该点,最远距离即可。
这里的距离指的是 曼哈顿距离

#include<bits/stdc++.h>using namespace std;const int MAX = 500010;const int inf = 0x3f3f3f3f;const int DIM = 2;struct node{    int l, r;    int d[DIM], maxn[DIM], minn[DIM];    inline void maintain()//初始化    {        l = r = 0;        for(int i = 0; i < DIM; i++)            maxn[i] = minn[i] = d[i];    }}tree[MAX];int D;bool operator < (const node &a, const node &b)//重载,从小到大{    return a.d[D] < b.d[D];}inline void Merge(int mid)//归并,向上更新{    int son[2] = {tree[mid].l, tree[mid].r};    for(int i = 0; i < 2; i++)    {        if(!son[i]) continue;        for(int j = 0; j < DIM; j++)        {            tree[mid].maxn[j] = max(tree[mid].maxn[j], tree[son[i]].maxn[j]);            tree[mid].minn[j] = min(tree[mid].minn[j], tree[son[i]].minn[j]);        }    }}int build(int l, int r, int now)//建树{    int mid = (l+r) >> 1;    D = now;    nth_element(tree+l, tree+mid, tree+r+1);//对于now维,以mid为中间,左边都是比它小,右边都是比它大。    tree[mid].maintain();//初始化    if(l < mid) tree[mid].l = build(l, mid-1, (now+1)%DIM);    if(r > mid) tree[mid].r = build(mid+1, r, (now+1)%DIM);    Merge(mid);    return mid;}int ans1, ans2;int partionMin(int o, int k)//求最小可能值{    int red = 0;    for(int i = 0; i < DIM; i++)    {        if(tree[k].d[i] > tree[o].maxn[i]) red += tree[k].d[i] - tree[o].maxn[i];        if(tree[k].d[i] < tree[o].minn[i]) red += tree[o].minn[i] - tree[k].d[i];    }    return red;}int partionMax(int o, int k)//求最大可能值{    int red = 0;    for(int i = 0; i < DIM; i++)    {        red += max(abs(tree[k].d[i] - tree[o].maxn[i]), abs(tree[k].d[i] - tree[o].minn[i]));    }    return red;}void queryMin(int o, int k)//求最小距离{    int dm = abs(tree[k].d[0] - tree[o].d[0]) + abs(tree[k].d[1] - tree[o].d[1]);    if(o == k) dm = inf;//自身点不算。    if(ans1 > dm) ans1 = dm;    int dl = tree[o].l ? partionMin(tree[o].l, k) : inf;    int dr = tree[o].r ? partionMin(tree[o].r, k) : inf;    if(dl < dr)    {        if(dl < ans1) queryMin(tree[o].l, k);        if(dr < ans1) queryMin(tree[o].r, k);    }    else    {        if(dr < ans1) queryMin(tree[o].r, k);        if(dl < ans1) queryMin(tree[o].l, k);    }}void queryMax(int o, int k)//求最大距离{    int dm = abs(tree[k].d[0] - tree[o].d[0]) + abs(tree[k].d[1] - tree[o].d[1]);    if(ans2 < dm) ans2 = dm;    int dl = tree[o].l ? partionMax(tree[o].l, k) : 0;    int dr = tree[o].r ? partionMax(tree[o].r, k) : 0;    if(dl > dr)    {        if(dl > ans2) queryMax(tree[o].l, k);        if(dr > ans2) queryMax(tree[o].r, k);    }    else    {        if(dr > ans2) queryMax(tree[o].r, k);        if(dl > ans2) queryMax(tree[o].l, k);    }}int main(){    int n, i, j;    while(~scanf("%d", &n))    {        for(i = 1; i <= n; i++)            for(j = 0; j < DIM; j++)            scanf("%d", &tree[i].d[j]);        int root = build(1, n, 0);        int Ans;        for(i = 1; i <= n; i++)        {            ans1 = inf;            ans2 = 0;            queryMin(root, i);            queryMax(root, i);            Ans = min(Ans, ans2 - ans1);        }        printf("%d\n", Ans);    }}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 交给学校查重的论文发错了怎么办啊 顺丰快递员把我的快递弄丢了怎么办 苹果6换了电池触屏不好用了怎么办 律协以律所被投诉不批准实习怎么办 提车时间没有写4s不给车怎么办 全店的人都知道我坐过牢怎么办 找了一个长得帅玩心重的老公怎么办 汽车左后轮油封漏油换了也漏怎么办 星露谷物语不小心把任务删了怎么办 饿了么商家版账号和密码忘了怎么办 红米4x手机里的照片全删了怎么办 微信表情包里编辑软文的数字怎么办 在转转上卖东西下单了想取消怎么办 丈夫的前儿子偷了我的钱我该怎么办 从日本寄的邮包被海关扣下了怎么办 卖家要求退货寄过去的货坏了怎么办 寄快递发货单丢了货发出去了怎么办 酷派手机电源键坏了开不了机怎么办 红米4a进水后开机就黑屏了怎么办 红米1s进水后开机了黑屏了怎么办 魅族手机已锁定魅族账号忘了怎么办 魅族5糸统升级后开不了机了怎么办 如果别人用电脑登了你的微信怎么办 消逝的光芒买错了买的普通版怎么办 在人人车卖了个车买家不过户怎么办 应用锁密码和密保问题都忘了怎么办 不小心在微信公众号发了消息怎么办 微信漂流瓶不能用了被投诉了怎么办 货物少了拉货的不承认少了怎么办 寄的快递号码留错了已经寄走怎么办 网购快递放在单位门卫室丢了怎么办 顺丰生鲜速配时效内食物坏了怎么办 竟尤理财跑路怎么办钱追的回来吗 博贝游戏用支付宝提不了现该怎么办 陌陌钱包没绑支付宝就体现了怎么办 鞋子让太阳晒的一只大一只小怎么办 美团不让上饿了么平台们商家怎么办 在汇通信诚租贷款买车被骗后怎么办 我的网银账户里的钱被盗了怎么办 老赖跑到国外去了还换了国籍怎么办 内裤把屁股两边磨得又肿又疼怎么办