题目

题目大意

给定平面上的 $n$ 个点和常数 $k$,求 $x$ 轴上的点 $p$ 到 $n$ 个点中距其最近的 $k$ 个点的距离之和的最小值。两点之间的距离定义为曼哈顿距离。

数据范围

$1\le k \le n \le 10^5$ 。

点的坐标是 $1$ 到 $10^8$ 之间的整数。

可能有重合的点。

分析

A optimization problem can have many possible solutions. Each solution has a value, and we wish to find a solution with the optimal (minimum or maximum) value. We call such a solution an optimal solution, as opposed to the optimal solution, since there may be several solutions that achieve the optimal value.

对于这种类型的最优化问题(optimization problems),思考的大方向是「降低问题的自由度」。
具体地说,找决策空间 $U$(或者称之为「状态空间」)的一个子集 $S$,使得 $S$ 满足:

  • 可以在 $S$ 中找到一个最优解
  • $S$ 中元素较少,遍历 $S$ 找最优解是可行的

如果已经选定 $k$ 个点,要在 $x$ 轴上找一点 $p$ 使得 $p$ 到这 $k$ 个点的曼哈顿距离之和最小。这个问题相当于

给定 $x$ 轴上的 $k$ 个点,在 $x$ 轴上找一点 $p$ 使得 $p$ 到这 $k$ 个点的距离之和最小。

这是一个经典问题,解是这 $k$ 的点的中位点(median)。奇数个点的中位点是中间的那个点,偶数个点的中位点是中间的两个点之间的线段上的任意一点(包括两端点)。

回到原问题,从上面的分析可以得到一个算法:枚举最优解中 $k$ 个点的横坐标的中位点。

将给定的 $n$ 个点构成的(可重)集合记做 $P$,
注意到对于 $n$ 个点中的任意 $k$ 个点,必然存在点 $p \in P$ 使得 $p$ 的横坐标是选出的 $k$ 个点的横标做的中位点。

所以我们只需要枚举点的横坐标即可。

将 $n$ 个点按横坐标从小到大排序,依次记为 $p_1, p_2, \dots, p_n$,设第 i 个点的坐标为 $(x_i , y_i)$ 。
令 $L_i $ 为 $p_1, p_2, \dots, p_{i-1}$ 中距 $(x_i,0)$ 最近的 $\lfloor n/2 \rfloor$ 个点与 $(x_i, 0)$ 的距离之和,$R_i$ 表示 $p_i, p_{i+1}, \dots, p_n$ 中距 $(x_i, 0)$ 最近 $(x_i, 0)$ 最近的 $n - \lfloor n/2 \rfloor$ 个点与 $(x_i, 0)$ 的距离之和。

答案即 $\min_{1\le i \le n} L_i + R_i$

参考实现


### Observation I

点 $p$ 到 $k$ 个最近点的距离之和一定可以在 $p$ 的横坐标取为 $n$ 个点中某个点的横坐标时取到。

### Observation II

CSA Round 84 Mahattan Center的更多相关文章

  1. CSA Round #84 The Sprawl

    题目 Analysis 曼哈顿距离($L1$ metric)最小生成树. Implementation 下面的代码参考了 gispzjz 在比赛中的提交. #include <bits/stdc ...

  2. CSA Round 84 Growing Trees

    题目 题目大意 给定一棵有 $n$ 个节点的树,边的权值每天变化.对于第 $i$ 条边,在第 $0$ 天,其权值为 $c_i$,每天权值变化 $a_i$(即,在第 $k$ 天,其权值为 $c_i + ...

  3. CSA Round #54 $\ $Voting

    CSA Round #54 \(\ \)Voting 题目大意: 原题网址:戳我戳我! 一次歌唱比赛中,一位歌手刚刚结束表演,评委正在打分. 一共有 \(n\) 位评委,他们每人可以打 \(1\) 分 ...

  4. Codeforces Beta Round 84 (Div. 2 Only)

    layout: post title: Codeforces Beta Round 84 (Div. 2 Only) author: "luowentaoaa" catalog: ...

  5. 题解-CSA Round#18 Randomly Permuted Costs

    Problem CSA Round 18 题意概要:给定一个有重边有自环 \(n\) 点 \(m\) 边的有向无环图(DAG),每条边有其权值,每当你走到一个点 \(x\) 时,所有从 \(x\) 连 ...

  6. Educational Codeforces Round 84 (Div. 2)

    Educational Codeforces Round 84 (Div. 2) 读题读题读题+脑筋急转弯 = =. A. Sum of Odd Integers 奇奇为奇,奇偶为偶,所以n,k奇偶性 ...

  7. Codeforces Beta Round #5 B. Center Alignment 模拟题

    B. Center Alignment 题目连接: http://www.codeforces.com/contest/5/problem/B Description Almost every tex ...

  8. csa Round #66 (Div. 2 only)

    csa66 Risk Rolls Time limit: 1000 msMemory limit: 256 MB   Alena and Boris are playing Risk today. W ...

  9. Bestcoder Round #84

    A题 Aaronson http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=718&pid=1001 感觉一 ...

随机推荐

  1. findsmb - 列出在子网上响应SMB名称查询的主机信息

    SYNOPSIS 总览 findsmb [子网广播地址] 描述 此perl脚本是Samba组件的一部分. findsmb是个用于打印出关于子网中响应SMB名字查询请求的主机信息的perl脚本.实际上它 ...

  2. 2017.12.6 计算机算法分析与设计---------Fibonacci数列

    (1)题目: 无穷数列1,1,2,3,5,8,13,21,34,55,--,称为Fibonacci数列.它可以递归地定义为: 第n个Fibonacci数可递归地计算如下: int fibonacci( ...

  3. OO2019第四单元作业总结

    一.本单元两次作业的架构设计  1.第一次作业 第一次作业由于时间仓促,没有过多的架构设计,就直接补全了所给的MyUmlInteraction类,导致整个程序的代码风格和效率都不高,在强测中也因此失掉 ...

  4. Wordpress菜单函数wp_nav_menu各参数详解及示例

    Wordpress菜单函数wp_nav_menu各参数详解及示例   注册菜单 首先要注册菜单,将以下函数添加至function.php函数里   register_nav_menus(array( ...

  5. 问题010:在Java中,什么是常量,什么是变量?

    Java中常量如何分类? 1.整数常量,所有的整数. 整数又分为 int (integer) 占用4个字节 一个字节占几个二进制位?8个二进制位,一个整型变量占32位二进制位 (内存中开辟出来的存储空 ...

  6. strong和weak

    ios中使用ARC后,内存管理使用了新的关键字:strong(强引用) 和 weak(弱引用),默认是strong引用 strong: 使用strong类型指针指向的对象,会一直保持指向,直到所有st ...

  7. jsp 生成验证码代码

    调用方法:在jsp页面用图像标签便可以直接调用如下是标签代码<img border=0 src="image.jsp">,只需要把该代码发在验证码要显示的区域就可以了) ...

  8. js数组中去重对象

    var allCourses = new Array();var coursesId = new Array();function findCourses() { Courses.data().eac ...

  9. HDU - 5017 Ellipsoid(模拟退火)

    题意 给一个三维椭球面,求球面上距离原点最近的点.输出这个距离. 题解 模拟退火. 把\(z = f(x, y)\)函数写出来,这样通过随机抖动\(x\)和\(y\)坐标就能求出\(z\). 代码 / ...

  10. 排序算法C语言实现——插入排序(优于冒泡)

    为什么插入排序要优于冒泡? 插入排序在于向已排序序列中插入新元素,主要的动作是移动元素,涉及1次赋值,即data[j] = data[j-1]; 而冒泡排序在于相邻元素交换位置,涉及3条赋值,即iTm ...