hdu 4311 & 4312 Meeting point 曼哈顿距离之和最小
hdu 4311
题意
平面上\(n(n\leq 1e5)\)个点,找一个点到其它所有点的曼哈顿距离之和最小。
思路
如果是找一个坐标使得所有点到其曼哈顿距离之和最小,那么将\(n\)个横坐标排个序,取中间的一个为答案的横坐标,将\(n\)个纵坐标排个序,取中间的一个为答案的纵坐标。原因就是绝对值$$y=|x-a_1|+|x-a_2|+...+|x-a_n|$$的图像为平底锅型或者是尖底。因为可以在平面上任意取点,所以可以取最优的\(x\)和\(y\).
但是这道题并不能够任意取点,而是限定在了\(n\)个点中。怎么办呢?
最常规的想法,就是将距离都算出来,取个最小值。然而直接算的话是\(O(n^2)\)的,数据量显然不允许。那么就换种算的方法。
还是先排序,考虑序列\(a_1,a_2,...,a_n\)(已升序排好),则$$|a_i-a_1|+|a_i-a_2|+...+|a_i-a_{i-1}|+|a_i-a_{i+1}|+...+|a_i-a_n|$$$$=((a_i-a_1)+(a_i-a_2)+...+(a_i-a_{i-1}))+((a_{i+1}-a_i)+...+(a_n-a_i))$$$$=(i-1)a_i-\sum_{k=1}{i-1}a_k-(n-i)*a_i+\sum_{k=i+1}{n}a_k$$$$=(2i-1-n)*a_i-\sum_{k=1}{i-1}a_k+\sum_{k=i+1}{n}a_k$$
于是可以预处理前缀和后缀和,就可以在\(O(n)\)的时间处理出来各个点对应的值了。
最后每个点的横坐标距离和纵坐标距离加起来取个最小值即可。
算法复杂度\(O(nlogn)\).
Code
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define maxn 100010
using namespace std;
typedef long long LL;
struct node {
LL x, y;
}a[maxn];
bool cmp1(int i, int j) { return a[i].x < a[j].x; }
bool cmp2(int i, int j) { return a[i].y < a[j].y; }
LL x[maxn], y[maxn], pr[maxn], su[maxn];
int id[maxn];
void work() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%lld%lld", &a[i].x, &a[i].y);
for (int i = 1; i <= n; ++i) id[i] = i;
sort(id+1, id+1+n, cmp1);
memset(pr, 0, sizeof pr);
memset(su, 0, sizeof su);
for (int i = 1; i <= n; ++i) pr[i] = pr[i-1] + a[id[i]].x;
su[n] = a[id[n]].x; for (int i = n-1; i > 0; --i) su[i] = su[i+1] + a[id[i]].x;
for (int i = 1; i <= n; ++i) x[id[i]] = (2*i-1-n)*a[id[i]].x - pr[i-1] + su[i+1];
sort(id+1, id+1+n, cmp2);
memset(pr, 0, sizeof pr);
memset(su, 0, sizeof su);
for (int i = 1; i <= n; ++i) pr[i] = pr[i-1] + a[id[i]].y;
su[n] = a[id[n]].y; for (int i = n-1; i > 0; --i) su[i] = su[i+1] + a[id[i]].y;
for (int i = 1; i <= n; ++i) y[id[i]] = (2*i-1-n)*a[id[i]].y - pr[i-1] + su[i+1];
LL ans = inf;
for (int i = 1; i <= n; ++i) ans = min(ans, x[i]+y[i]);
printf("%lld\n", ans);
}
int main() {
int T;
scanf("%d", &T);
while (T--) work();
return 0;
}
hdu 4312
题意
平面上\(n(n\leq 1e5)\)个点,找一个点到其它所有点的切比雪夫距离之和最小。
思路
将切比雪夫距离转化为曼哈顿距离,方法为将坐标转45度。即将\((x,y)\)的坐标映射为\((x+y,y-x)\).
然后就可以直接套上一题了,最终答案除以2.
Code
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define maxn 100010
using namespace std;
typedef long long LL;
struct node {
LL x, y;
}a[maxn];
bool cmp1(int i, int j) { return a[i].x < a[j].x; }
bool cmp2(int i, int j) { return a[i].y < a[j].y; }
LL x[maxn], y[maxn], pr[maxn], su[maxn];
int id[maxn];
void work() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
LL xx, yy;
scanf("%lld%lld", &xx, &yy);
a[i].x = xx+yy, a[i].y = yy-xx;
}
for (int i = 1; i <= n; ++i) id[i] = i;
sort(id+1, id+1+n, cmp1);
memset(pr, 0, sizeof pr);
memset(su, 0, sizeof su);
for (int i = 1; i <= n; ++i) pr[i] = pr[i-1] + a[id[i]].x;
su[n] = a[id[n]].x; for (int i = n-1; i > 0; --i) su[i] = su[i+1] + a[id[i]].x;
for (int i = 1; i <= n; ++i) x[id[i]] = (2*i-1-n)*a[id[i]].x - pr[i-1] + su[i+1];
sort(id+1, id+1+n, cmp2);
memset(pr, 0, sizeof pr);
memset(su, 0, sizeof su);
for (int i = 1; i <= n; ++i) pr[i] = pr[i-1] + a[id[i]].y;
su[n] = a[id[n]].y; for (int i = n-1; i > 0; --i) su[i] = su[i+1] + a[id[i]].y;
for (int i = 1; i <= n; ++i) y[id[i]] = (2*i-1-n)*a[id[i]].y - pr[i-1] + su[i+1];
LL ans = inf;
for (int i = 1; i <= n; ++i) ans = min(ans, x[i]+y[i]);
printf("%lld\n", ans/2);
}
int main() {
int T;
scanf("%d", &T);
while (T--) work();
return 0;
}
hdu 4311 & 4312 Meeting point 曼哈顿距离之和最小的更多相关文章
- Hdu4311 || 4312Meeting point-1/-2 n个点中任意选一个点使得其余点到该点曼哈顿距离之和最小
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...
- 某个点到其他点的曼哈顿距离之和最小(HDU4311)
Meeting point-1 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- 【HDU 4311】Meeting point-1(前缀和求曼哈顿距离和)
题目链接 正经解法: 给定n个点的坐标,找一个点,到其他点的曼哈顿距离之和最小.n可以是100000.大概要一个O(nlogn)的算法.算曼哈顿距离可以把x和y分开计算排好序后计算前缀和就可以在O(1 ...
- 51Nod 1108 距离之和最小 V2 1096 距离之和最小 中位数性质
1108 距离之和最小 V2基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注三维空间上有N个点, 求一个点使它到这N个点的曼哈顿距离之和最小,输出这个最小 ...
- HDU 4311 Meeting point-1 求一个点到其它点的曼哈顿距离之和
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4311 解题报告:在一个平面上有 n 个点,求一个点到其它的 n 个点的距离之和最小是多少. 首先不得不 ...
- 51nod 1096 距离之和最小 1108 距离之和最小 V2
[题解] 很显然在一条坐标轴上到各个点距离之和最小的点就是它们的中位数.怎么证明呢?我们假设现在找的某个点x左边有a个点,右边有b个点(a>b).我们把x向左移动d个单位,并保证x左边依然有a个 ...
- 51Nod 1110 距离之和最小 V3 中位数 思维
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 X轴上有N个点,每个点除了包括一个位置数据X[i],还包括一个权值W[i].点P到点P[i]的带权距离 = 实际距离 ...
- 51nod1110 距离之和最小 V3
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 X轴上有N个点,每个点除了包括一个位置数据X[i],还包括一个权值W[i].该点到其他点的带权距离 = 实际距离 * 权值.求X轴上 ...
- 【51NOD】1096 距离之和最小
[算法]数学 [题解] 其实就是求中位数,奇数个点就是最中间的点,偶数个点就是最中间两个点和它们之间的区域皆可(所以偶数不必取到两点正中央,取两点任意一点即可). 我们可以想象现在x轴上有n个点,我们 ...
随机推荐
- centos 安装 python3 分类链接
上一篇文章描述了如何安装python3,但是在后续安装pip便不断报出缺少各类模块,安装一个又需要依赖另一个,导致安装过程非常繁琐.究其原因,我是安装centos-minimal版本,有许多功能不是完 ...
- 16Shell脚本—计划任务服务程序
计划任务服务程序 尽管我们现在已近有了功能彪悍的脚本程序来执行一些批处理工作,但是,如果仍然需要每天凌晨两点敲击键盘回车键来执行这个脚本程序,这简直太痛苦了.为此,我们需要学习如何设置服务器的计划任务 ...
- Vue实例和生命周期
创建一个Vue实例 每个Vue应用都是通过Vue函数创建一个新的Vue实例开始: var vm = new Vue({ //选项 }) 数据与方法 当一个Vue实例被创建时,它向Vue的响应式系统中加 ...
- css制作三角形,下拉框三角形
网站制作中常常需要下拉框,而如果下拉框如果只是单纯的矩形则会显得太过单调,所以这次教大家利用css制作三角形放在矩形上面 首先利用css制作三角形 div { width:0px; height:0p ...
- jquery中arrt()和prop()的区别
在jQuery中,attr()函数和prop()函数都用于设置或获取指定的属性,它们的参数和用法也几乎完全相同. 但不得不说的是,这两个函数的用处却并不相同.下面我们来详细介绍这两个函数之间的区别. ...
- LeetCode(258) Add Digits
题目 Given a non-negative integer num, repeatedly add all its digits until the result has only one dig ...
- eclipse使用技巧的网站收集——转载(二)
写代码离不开文本编辑器,看代码也离不开,iar和keil编辑和阅读简直一般般了,因此使用eclipse可以看看代码,提高效率.网上有几个博客的文章,这里收集一下,以备忘. 以下文章转载自:http:/ ...
- stm32F4中断分析-HAL库
详细可以参考: STM32使用HAL库操作外部中断——实战操作 https://www.cnblogs.com/wt88/p/9624103.html /** ******************** ...
- 数学基础:HDU2802-F(N)(寻找循环节)
F(N) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissi ...
- Linux学习-延伸正则表达式
grep 默认仅支持基础正则表达式,如果要使用延伸型正则 表达式,你可以使用 grep -E , 不过更建议直接使用 egrep !直接区分指令比较好记忆!其 实 egrep 与 grep -E 是类 ...