HYSBZ bzoj 1941 Hide and Seek

2023-11-02

Problem

www.lydsy.com/JudgeOnline/problem.php?id=1941
vjudge.net/contest/187908#problem/B

Reference

[BZOJ1941][Sdoi2010]Hide and Seek(kd-tree)

Meaning

给出平面上 n 个点,要选其中一个,使得它到其它点的 曼哈顿最远距离和最近距离的差 最小,求这个最小的差。

Analysis

用 K-D树对每个点都求离它最远的点和最近的点的距离,相减更新答案。

Notes

这题集合了 K-D树求最远点和最近点的套路,主要在于那两个估价减枝。
在建树的时候,处理出每个点划分的那个区域里的横、纵坐标的最大、最小值,相当于找到包住这个区域的那个大矩形。
在最远点估价的时候,相当于用这个矩形的四个顶点之一(离目标点最远那个)来估价;在最近点时,相当于判断目标点在不在这个矩形内,如果在,直接不算距离,(某一维)在矩形外才算上目标点(在该维度)离最近的矩形边界的距离。

Code

#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 500000, D = 2, X = 1e8, Y = X;

int idx;

struct node
{
    int v[D];
    bool operator < (const node &rhs) const
    {
        return v[idx] < rhs.v[idx];
    }
} kdt[N], aim;

int lc[N], rc[N], big[N][D], sml[N][D];

void pushup(int p)
{
    for(int i = 0; i < D; ++i)
    {
        int &b = big[p][i], &s = sml[p][i];
        if(~lc[p])
        {
            b = max(b, big[lc[p]][i]);
            s = min(s, sml[lc[p]][i]);
        }
        if(~rc[p])
        {
            b = max(b, big[rc[p]][i]);
            s = min(s, sml[rc[p]][i]);
        }
    }
}

int build(int l, int r, int d)
{
    idx = d & 1;
    int m = l + r >> 1;
    nth_element(kdt + l, kdt + m, kdt + r + 1);
    lc[m] = rc[m] = -1;
    for(int i = 0; i < D; ++i)
        big[m][i] = sml[m][i] = kdt[m].v[i];
    if(l < m)
        lc[m] = build(l, m - 1, d + 1);
    if(r > m)
        rc[m] = build(m + 1, r, d + 1);
    pushup(m);
    return m;
}

inline int manhattan(int p)
{
    return abs(aim.v[0] - kdt[p].v[0]) +
            abs(aim.v[1] - kdt[p].v[1]);
}

int far, near; // 最远距离、最近距离

/* 最远距离的估价 */
int dis_b(int p)
{
    int res = 0;
    for(int i = 0; i < D; ++i)
        res += max(
            abs(aim.v[i] - big[p][i]),
            abs(aim.v[i] - sml[p][i])
        );
    return res;
}

void query_b(int p)
{
    far = max(far, manhattan(p));
    int dl = 0, dr = 0;
    if(~lc[p])
        dl = dis_b(lc[p]);
    if(~rc[p])
        dr = dis_b(rc[p]);
    if(dl > dr)
    {
        if(dl > far)
            query_b(lc[p]);
        if(dr > far)
            query_b(rc[p]);
    }
    else
    {
        if(dr > far)
            query_b(rc[p]);
        if(dl > far)
            query_b(lc[p]);
    }
}

/* 最近距离的估价 */
int dis_s(int p)
{
    int res = 0;
    for(int i = 0; i < D; ++i)
        if(aim.v[i] > big[p][i]) // 超出上边界
            res += aim.v[i] - big[p][i];
        else if(aim.v[i] < sml[p][i]) // 超出下边界
            res += sml[p][i] - aim.v[i];
    return res;
}

void query_s(int p)
{
    // 最近距离不包括到自己的距离
    if(int d = manhattan(p))
        near = min(near, d);
    int dl = X + Y, dr = X + Y;
    if(~lc[p])
        dl = dis_s(lc[p]);
    if(~rc[p])
        dr = dis_s(rc[p]);
    if(dl < dr)
    {
        if(dl < near)
            query_s(lc[p]);
        if(dr < near)
            query_s(rc[p]);
    }
    else
    {
        if(dr < near)
            query_s(rc[p]);
        if(dl < near)
            query_s(lc[p]);
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    for(int i = 0; i < n; ++i)
        cin >> kdt[i].v[0] >> kdt[i].v[1];
    int rt = build(0, n - 1, 0), ans = X + Y;
    for(int i = 0; i < n; ++i)
    {
        aim = kdt[i];
        far = 0;
        near = X + Y;
        query_b(rt);
        query_s(rt);
        ans = min(ans, far - near);
    }
    cout << ans << '\n';
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HYSBZ bzoj 1941 Hide and Seek 的相关文章

  • xml文件报错Unable to resolve column ‘xxx‘

    项目场景 问题描述 我在使用mybatis的逆向工程时生成的xml文件报错Unable to resolve column xxx 原因分析 需要连接到数据库 解决方案 点击右侧 填写数据库信息 点击测试 报错的话点击下放Set time
  • shell 格式化输出密码

    格式化输出 etc passwd 效果如下 root zabbix server day6 awk F BEGIN print 用户名 UID 家目录 print 1 3 6 etc passwd 用户名 UID 家目录 root 0 ro

随机推荐

  • Unity 移动方法总结

    Unity移动方法总结 在Unity3D中 有多重方式可以改变物体的坐标 实现移动的目的 其本质是每帧改变物体的position 通过Transform组件移动物体 Transform组件用于描述物体在空间中的状态 它包括位置 positi
  • transformers库的使用【二】tokenizer的使用,模型的保存自定义

    使用标记器 tokenizer 在之前提到过 标记器 tokenizer 是用来对文本进行预处理的一个工具 首先 标记器会把输入的文档进行分割 将一个句子分成单个的word 或者词语的一部分 或者是标点符号 这些进行分割以后的到的单个的wo
  • C——编译预处理

    编译预处理 1 宏定义 2 文件包含 3 条件编译 C语言提供的预处理 在编译之前进行 主要有三种 宏定义 文件包含和条件编译 预处理命令不是C语句 不用加分号 1 宏定义 形式 define 宏名 替换文本 define 宏名 参数 替换
  • Python元组、列表、字典、字符串常用方法超详细总结!!!

    文章目录 1 列表 list 1 1 len 1 2 max 和min 1 3 reverse 1 4 sort 1 5 clear 1 6 remove 1 7 insert 和pop 2 元组 tuple 2 1 len 2 2 cou
  • test2这篇博客的目的是test我做的小程序,请勿打开

    这篇博客的目的是test我做的小程序 请勿打开
  • SpringBoot多数据源动态切换,不影响业务逻辑正常运行,服务高可用

    SpringBoot多数据源动态切换 不影响业务逻辑正常运行 服务高可用 本文使用Spring Boot 2 4 10版本和MyBatis实现多数据源动态切换 当主库MySQL宕机后自动切换到容灾PostgreSQL数据库 数据库及数据表示
  • Altium Designer -- EMC/EMI电路设计经验

    一 基本概念 参看 电磁兼容原理及应用 讲的相当的不错 随着科学技术的不断发展 各种电气和电子设备已广泛应用于国民经济的各个部门以及人们的日常生活中 电气和电子设备在正常运行的同时 也往外发射有用或无用的电磁能量 这些能量会影响其它设备的正
  • 【React】dva-cli建立脚手架后引用css 无效

    用dva cli作为脚手架建立工程后 开始尝试编写页面 然后立马发现一个坑爹的问题 在我less文件里面写了一个class 比如 MainHead 但是编译出来之后发现css文件里面变成了 MainHead xuaz 多了一个后缀 坑爹嘛这
  • JavaScript 预解析(面试经常问)

    文章目录 预解析 预解析 解析器运行 JS 分为哪两步 预解析 执行代码 预解析 js 引擎会把 js里面所有 var 还有 function 提前到当前作用域的最前面 执行代码 从上到下执行 预解析分为 变量预解析 变量提升 和函数预解析
  • 数字图像处理第一二章

    什么是数字图像处理 数字图像处理是指借助于数 计算机来处理数字图像 当x y和灰度值f是有限的离散数值时 称该图像为数字图像 一幅图像可定义为一个二维函数f x y 其中x和y是空间 平面 坐标 而在任一对空间坐标 x y 处的幅值f称为图
  • infix 关键字

    infix适用于有单个参数的扩展函数 如果一个函数使用了infix 关键字 接收者和函数之间的点操作 以及参数的一对括号可以省略 fun String printWithDefault0 default String print this
  • 动态路由协议BGP配置实战

    1 边界网关协议BGP BGP是自治系统路由协议 用于AS间交换路由信息 通常使用在运营商 运营商之间或是企业 运营商之间 目前广为使用的是BGP 4 支持CIDR BGP协议使用TCP179端口传输 同一AS的路由之间传输的协议称为IBG
  • 在HAL库中NVIC中断配置

    中断优先级分组配置 void HAL NVIC SetPriorityGrouping uint32 t PriorityGroup 配置函数 define IS NVIC PRIORITY GROUP GROUP GROUP NVIC P
  • 关于监控方案的一点想法供参考

    Author Skate Time 2017 12 11 关于监控方案的一点想法供参考 1 监控目标 监控的直接目标 及时 准确的发现潜在事件 并辅助运维人员处理生产事件 消除生产事件专家和高手与一线员工的区别 监控的增值目标 通过高度的可
  • SW3516中文资料书

    SW3516 是一款高集成度的快充车充芯片 支持 A C 口任意口快充输出 支持双口独立限流 其集成了 5A 高效率同步降压变换器 支持 PPS PD QC AFC FCP SCP PE SFCP 低压直充等多种快充协议 CC CV 模式
  • unity 使用声网(Agora)实现语音通话

    第一步 先申请一个声网账号 Agora官网链接 https console shengwang cn 第二步在官网创建项目 选择无证书模式 证书模式需要tokenh和Appld才能通话 第三步 官网下载SDK 然后导入到unity 也可以直
  • VulnHubBreach1.0[渗透测试]新手必看

    靶机下载地址 https download vulnhub com breach Breach 1 0 zip 前言 将下载好的靶场导入VMware 虚拟机设置网络模式为nat模式 即可开启渗透 阅读readme txt 作为多部分系列的第
  • linux 共享存储 iostat,Linux环境下存储监控工具nfsiostat介绍

    我对Linux下存储管理和监控工具的缺乏感到非常不满 虽然如此 我还是积极在寻找适合的工具 除了等待更好的工具出现 或自己开发一款 外 我们必须好好利用现有工具的功能 sysstat监控工具家族中的一员 在以前的文章中 我曾经介绍过iost
  • mmdetection常见问题总结

    mmdetection运行以及问题总结 最近因为工作需要 跑了下mmdetection 复现了论文的精度 总结下其中遇到的问题 希望对大家有帮助哦 1 环境设置 操作系统 ubuntu16 04 python3 7 pytorch1 6 0
  • HYSBZ bzoj 1941 Hide and Seek

    Problem www lydsy com JudgeOnline problem php id 1941 vjudge net contest 187908 problem B Reference BZOJ1941 Sdoi2010 Hi