P7561[JOISC 2021 Day2] 道路の建設案 (Road Construction) 题解

题目描述

JOI 国是一个 \(x\times y\) 的二维平面,王国里有 \(n\) 个城镇,分别编号为 \(1, 2, \cdots, n \in [1,2.5 \times 10^5]\),其中第 \(i\) 个城镇的 坐标 为 \((x_i, y_i)\)。

在 JOI 国,正计划修建连接两座城镇的路(下文简称:「修路的项目」),路有 \(k\) 条。连接两个不同的城镇 \(a\) 和 \(b\) 将花费 \(|x_a − x_b| + |y_a − y_b|\) 元。若有一条连接 \(c\),\(d\) 的路,则不需要也不可以在建一条连接 \(d\),\(c\) 的路,因为它们是相同的。

你要管理这个「修路的项目」,为了计算花费情况,你得弄明白连接一些城镇所需的花费。在这 \(\dfrac{n\cdot(n-1)}{2}\) 条道路中,你想了解最便宜的 \(k\) 条道路的花费。

给你城镇的坐标以及 \(k\),请计算最便宜的 \(k\) 条路所需要的钱。

解析

首先你要知道什么是曼哈顿距离和切比雪夫距离及相互转化。

推荐学习曼哈顿距离与切比雪夫距离的互化

现在我把点坐标转化后就是要求解这样一个问题:

\[\max(|x_i-x_j|,|y_i-y_j|)
\]

选出前 \(k\) 小。

我们可以二分一下第 \(k\) 小的值 \(mid\),再 check 有没有 \(k\) 个距离小于 mid

同时我们不需要真正数有多少点对,点对数 \(≥k\) 时直接返回 true 即可。

具体操作是先按照 \(x\) 排序。

假设当前到了 \(x_i\) ,将所有 \([x_i-mid,x_i]\) 的点放入 set 里面,

之前在 \([x_{i-1}-mid,x_{i-1}]\) 里面的但不在 \([x_i-mid,x_i]\) 删掉(用双指针维护)。

然后在 set 里面先二分找到 \(y_i-mid\),枚举到 \(y_i + mid\) ,每枚举到一个就 ++ans

ans >= k 的时候就直接 return

最后如何求出答案?

找到第 \(k\) 小的值 \(mid\) 了之后,再 check 一次 \(mid-1\),这样一定可以找到小于 \(k\) 个长度小于 \(mid\) 的长度,最后再用 \(mid\) 把 \(k\) 补满,就是答案。

因为 \(ans >= k\) 会 return 所以严格 \(O(n\log n)\)。

温馨提示

1.因为转化为切比雪夫距离,又要互相加减,所以要开 long long

2.用 multiset ,因为可能有相同长度。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 3e7 + 10;
int n, k;
ll x,y,an[N],ans = 0,l,r,mid;
queue<int>q;
struct node{
ll x, y;
bool operator <(const node a)const{
return x < a.x;
}
}p[N];
struct Node{
ll x, y;
bool operator <(const Node a)const{
return y < a.y;
}
};
multiset<Node>s;
void input(){
cin>>n>>k;
for(int i = 1; i <= n; ++i){
cin>>x>>y;
p[i].x = x - y;
p[i].y = x + y;
}
sort(p + 1,p + 1 + n);
}
bool check(ll mid){
q = queue<int>();
s = multiset<Node>();
ans = 0;
for(int i = 1; i <= n; ++i){
while(q.size() && p[i].x - p[q.front()].x > mid){
multiset<Node>:: iterator w = s.find((Node){0,p[q.front()].y});
s.erase(w);
q.pop();
}
multiset<Node>::iterator lz = s.lower_bound((Node){0,p[i].y - mid});
while(lz != s.end() && (*lz).y <= p[i].y + mid){
an[++ans] = max(abs((*lz).x - p[i].x),abs((*lz).y - p[i].y));
if(ans >= k) return 1;
++lz;
}
q.push(i);
s.insert((Node){p[i].x,p[i].y});
}
return 0;
}
void op(){ l = 0,r = 4e9,mid;
while(l < r){
mid = (l + r) >> 1;
if(check(mid)){
r = mid;
}else{
l = mid + 1;
}
}
check(l - 1);
}
void output(){
sort(an + 1,an + 1 + ans);
int i;
for(i = 1; i <= ans; ++i){
cout<<an[i]<<'\n';
}
for(; i <= k; ++i){
cout<<l<<'\n';
}
}
int main(){
cin.tie(0)->sync_with_stdio(false);
input();
op();
output();
return 0;
}

P7561[JOISC 2021 Day2] 道路の建設案 (Road Construction) 题解的更多相关文章

  1. 【LOJ】#3034. 「JOISC 2019 Day2」两道料理

    LOJ#3034. 「JOISC 2019 Day2」两道料理 找出最大的\(y_{i}\)使得\(sumA_{i} + sumB_{y_i} \leq S_{i}\) 和最大的\(x_{j}\)使得 ...

  2. 【LOJ】#3033. 「JOISC 2019 Day2」两个天线

    LOJ#3033. 「JOISC 2019 Day2」两个天线 用后面的天线更新前面的天线,线段树上存历史版本的最大值 也就是线段树需要维护历史版本的最大值,后面的天线的标记中最大的那个和最小的那个, ...

  3. Loj3033 JOISC 2019 Day2两个天线

    Loj3033 JOISC 2019 Day2两个天线 下午唯一听懂的题目但,但还是比较模糊.写一篇题解来加深一下印象. 题目大意:给定\(n\)根天线,第\(i\)跟天线的高度为\(h_i\),切它 ...

  4. Solution -「JOISC 2021」「LOJ #3491」道路建设

    \(\mathcal{Description}\)   Link.   平面上有 \(n\) 个互不重合的点 \((x_{1..n},y_{1..n})\),求其两两曼哈顿距离的前 \(m\) 小值. ...

  5. GDKOI 2021 Day2 PJ 去世记

    比赛时和昨天一样困,后面的大奆打代码的速度简直了 T1 用 2.4.6.8 来与 5 抵消掉末尾的 0 ,然后用周期问题的方法直接乘起来并取个位 #include<bits/stdc++.h&g ...

  6. loj2876 水壶 [JOISC 2014 Day2] kruscal重构树

    正解:kruscal重构树+bfs 解题报告: 我永远喜欢loj! 感觉这题和这题挺像的,,,预处理和解题方法都是,,,所以大概整体二分能过去? 但因为做这题主要是入门一下kruscal重构树,,,所 ...

  7. [LOJ#2878]. 「JOISC 2014 Day2」邮戳拉力赛[括号序列dp]

    题意 题目链接 分析 如果走到了下行车站就一定会在前面的某个车站走回上行车站,可以看成是一对括号. 我们要求的就是 类似 代价最小的括号序列匹配问题,定义 f(i,j) 表示到 i 有 j 个左括号没 ...

  8. bzoj4244 & loj2878. 「JOISC 2014 Day2」邮戳拉力赛 括号序列+背包

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4244 https://loj.ac/problem/2878 题解 挺妙的一道题. 一开始一直 ...

  9. LOJ #2877. 「JOISC 2014 Day2」交朋友 并查集+BFS

    这种图论问题都挺考验小思维的. 首先,我们把从 $x$ 连出去两条边的都合并了. 然后再去合并从 $x$ 连出去一条原有边与一条新边的情况. 第一种情况直接枚举就行,第二种情况来一个多源 bfs 即可 ...

  10. LOJ #2876. 「JOISC 2014 Day2」水壶 BFS+最小生成树+倍增LCA

    非常好的一道图论问题. 显然,我们要求城市间的最小生成树,然后查询路径最大值. 然后我们有一个非常神的处理方法:进行多源 BFS,处理出每一个城市的管辖范围. 显然,如果两个城市的管辖范围没有交集的话 ...

随机推荐

  1. 粘包,自定义协议,struct模块,粘包解决终极大招

    粘包: 1.粘包问题出现的原因: (udp不会出现粘包问题) 1.1.tcp是流式协议,数据像水流一样黏在一起,没有任何边界区分 1.2.收数据没收干净,有残留,就会下一次结果混淆在一起去(客户端接受 ...

  2. Mysql简明语法

    show databases ; use mybatis; show tables ; select * from user; select * from user where id=1; updat ...

  3. 从零开始学Vue(二~三)—— Vue 实例 / 模板语法(插值、指令)

    概述 vue.js作为现在笔记热门的JS框架,使用比较简单易上手,也成为很多公司首选的JS框架. 但是对于初学者可能学起来有些麻烦,所以推出<从零开始学Vue>系列博客,本系列计划推出19 ...

  4. Yii2批量插入数据

    方法一 yii2一次插入多行数据  /** * @inheritdoc 批量添加 * @params $add array 添加数据 */ public function add_all($add) ...

  5. Prometheus监控之SNMP Exporter介绍和数据展现

    由于技术能力有限,文章仅能进行简要分析和说明,如有不对的地方,请指正,谢谢. 1 SNMP协议介绍 SNMP协议全称是:Simple Network Management Protocol,译为简单网 ...

  6. MySQL中的Join 的算法(NLJ、BNL、BKA)

    本文已收录至Github,推荐阅读 Java随想录 微信公众号:Java随想录 目录 摘要 什么是Join Index Nested-Loop Join Block Nested-Loop Join ...

  7. Java动态调用实体的get方法

    /** * 动态调用实体的get方法(注意返回值) * @param dto 实体 * @param name 动态拼接字段 * @return {@link String} * @date 2021 ...

  8. pngquant 在 Windows 上压缩带中文路径的 png 图片

    pngquant 是一个优秀的 png 压缩工具,但是在 Windows 上不支持目录中带有 unicode 字符(例如中文)的文件.所以要用一个折中的办法(即标准输入)让 pngquant 压缩目录 ...

  9. 2020-03-02:在无序数组中,如何求第K小的数?

    2020-03-02:在无序数组中,如何求第K小的数? 福哥答案2021-03-02: 1.堆排序.时间复杂度:O(N*lgK).有代码. 2.单边快排.时间复杂度:O(N).有代码. 3.bfprt ...

  10. KubeCon EU 2023 落幕,哪些技术趋势值得关注?

    KubeCon+CloudNativeCon 是云原生领域的技术盛会,上个月月末,在荷兰阿姆斯特丹举办的欧洲 KubeCon+CloudNativeCon 刚刚落下帷幕,此次大会吸引了10000多名参 ...