1 条题解
-
0
::::info[题意]{open} 这题第一眼很像我前几天做的 P3076,但是该题是一次只能载一个乘客,而本题是可以同时载多个。
有一条数轴,需要从 走到 ,且路程必须包含 (),求最短路程。 ::::
::::info[分析]{open}
本题是一道区间合并贪心问题。
由于本题可以同时载多个乘客,而我们本来也是从 走到 ,所以所有正方向的乘客都可以顺路送到。
而对于负方向的乘客,要让往回绕的路程最短,需要找出怎么才能一次送尽量远的距离,而最短距离就是所有线段的交的长度的两倍(因为往返)。
:::info[重叠区间证明]{open} 借用
https://www.luogu.com.cn/user/907119
对于 、 这两个重叠区间,放在一段中往返路程为 ,而单独往返为 $2(r_2-l_2)+2(r_1-l_1)=2(r_2-l_1)+2(r_1-l_2) \geqslant 2(r_2-l_1)$,故放在一段中往返不劣。 :::
:::error[一个误区]{open} 答案为 。
惨痛教训。 :::
:::info[不重叠区间证明]{open} 再看这张图:

对于 、 这两个不重叠区间,如果分别往返,路程为 ,而放在一段中往返路程为 $2(r_3-l_2)=2(r_3-l_3)+2(l_3-r_2)+2(r_2-l_2) \geqslant 2(r_3-l_3)+2(r_2-l_2)$,故分别往返不劣。 ::: ::::
::::success[正确代码]{open}
#include <bits/stdc++.h> using namespace std; #define int long long #define INF 1e18 struct node { int s, t; bool operator<(node x)const { return s < x.s; } }; int n, m, n1; node a[300005]; signed main() { ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); cin >> n >> m; for(int i = 1, s, t; i <= n; ++ i) { cin >> s >> t; if(s > t) // 负方向才存! a[++ n1] = {t, s}; } sort(a + 1, a + n1 + 1); int nows = a[1].s, nowt = a[1].t, ans = m; // nows,nowt 当前区间的始末 for(int i = 2; i <= n; ++ i){ if(a[i].s <= nowt) // 与当前区间重叠 nowt = max(nowt, a[i].t); // 延展区间 else ans += 2 * (nowt - nows), nows = a[i].s, nowt = a[i].t; // 结算该区间答案,并更新区间位置 } ans += 2 * (nowt - nows); // 别忘了! cout << ans; return 0; }::::
- 1
信息
- ID
- 4851
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者