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个点,我们 ...
随机推荐
- git 指令记录
由于之前一直用svn 用git也是用图形化的工具 还是要了解一下git指令 因为都是版本控制工具 有很多相似之处 所以理解起来也比较轻松 仓库: github上面的项目 工作目录下面的所有文件都不外乎 ...
- Android读书笔记四
第四章 这是一次源代码之旅,学到了如何下载和编译Android源代码和Linux内核源代码.来详细阐述一下一些具体过程 一.Android源代码下载环境 1.安装下载Android源代码的环境配置 ( ...
- NOIP模拟赛 czy的后宫
[题目描述] czy要妥善安排他的后宫,他想在机房摆一群妹子,一共有n个位置排成一排,每个位置可以摆妹子也可以不摆妹子.有些类型妹子如果摆在相邻的位置(隔着一个空的位置不算相邻),就不好看了.假定每种 ...
- Ubuntu下搭建多用户多权限ftp
#1.切换root用户模式 (已在root模式下的请忽略) sudo -i #然后提示你输入当前用户密码,输入密码后回车后如果密码正确控制台就变成root@***:/# 了. #2.更新软件源 apt ...
- CentOS7 安装操作命令
#timedatectl set-timezone Asia/Shanghai 关闭SELinux vi /etc/sysconfig/selinux #SELINUX=enforcing SELIN ...
- python-闭包函数和装饰器
目录 闭包函数 什么是闭包? 两种为函数传参的方式 使用参数的形式 包给函数 闭包函数的应用 闭包的意义: 装饰器 无参装饰器 什么是装饰器 为什么要用装饰器 怎么用装饰器 完善装饰器 闭包函数 什么 ...
- JAVA基础篇—抽象类,抽象方法
class Shape package com.shape; public abstract class Shape { double area;// double per;// String col ...
- SDUST第十一次oj作业液晶显示问题
Problem H: 液晶显示 Time Limit: 1 Sec Memory Limit: 32 MBSubmit: 3246 Solved: 1594[Submit][Status][Web ...
- Linux学习-什么是例行性工作排程
那么 Linux 的例行性工作是如何进行排程的呢?所谓的排程就是将这些工作安排执行的流程之意! 咱们的 Linux 排程就是透过 crontab 与 at 这两个东西! Linux 工作排程的种类: ...
- jmeter throughput controller
工作方式:可以按规定次数执行,也可以选择按百分比执行,其中的百分比必须是10,20,30类似的整数. 使用场景:可以随机的去按百分比浏览网址. 以下是具体脚本: