1 条题解
-
0
自动搬运
来自洛谷,原作者为

phoenixzhan
**搬运于
2025-08-24 22:53:05,当前版本为作者最后更新于2024-02-01 11:42:22,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
设最多可以选出 条彼此无交的线段(这是个经典的贪心问题),显然我们可以构造出 组的方案:任取其中一条线段作为其他 条线段的 pair,于是只需要判断是否有 组的方案。
由于最多可以选出 条无交线段,考察最后答案的 组线段中,一条线段 和它的 pair ,显然 和 有交,且 和 无交。有了这些性质,随便贪一贪就可以了。把所有线段按右端点排序,每次选出两条右端点最小的线段作为 和 ,即可。
#include <bits/stdc++.h> using namespace std; #define pb push_back #define pii pair<int, int> #define piii tuple<int, int, int> #define mp make_pair #define mt make_tuple #define fi first #define se second #define deb(var) cerr << #var << '=' << (var) << "; " #define int long long namespace Loser { int n; struct Seg { int fi, se, id; } a[500010]; bool cmp(Seg a, Seg b) { return a.se == b.se ? a.fi < b.fi : a.se < b.se; } int cnt; vector<int> ans; int tot; vector<pii> res; void main() { cin >> n; for (int i = 1; i <= n; i++) cin >> a[i].fi >> a[i].se, a[i].id = i; sort(a + 1, a + n + 1, cmp); for (int i = 1, r = 0; i <= n; i++) { if (a[i].fi < r) continue; cnt++; r = a[i].se; ans.pb(a[i].id); } int pre = 0; for (int i = 1, r = 0, R = 0; i <= n; i++) { if (a[i].fi < R) { if (a[i].fi >= r && !pre) pre = i; continue; } int k = i + 1; if (pre) { k = pre; pre = 0; tot++, res.pb(mp(a[i].id, a[k].id)); r = R = a[i].se; continue; } while (k <= n && a[k].fi < r) k++; if (k <= n) tot++, res.pb(mp(a[i].id, a[k].id)); r = a[i].se, R = a[k].se; i = k; } deb(cnt), deb(tot); if (tot >= cnt) { cout << tot << '\n'; for (auto i: res) cout << i.fi << ' ' << i.se << '\n'; return; } cout << cnt - 1 << '\n'; for (int i = 1; i < ans.size(); i++) cout << ans[i] << ' ' << ans[0] << '\n'; } } signed main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int T = 1; while (T--) Loser::main(); return 0; }
- 1
信息
- ID
- 9458
- 时间
- 500ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者