CF1389F Bicolored Segments
CF1389F Bicolored Segments
题目大意:
给你 \(n\) 条线段 \([l_1, r_1], [l_2, r_2], \ldots, [l_n, r_n]\)。线段有两种颜色,第 \(i\) 条线段的颜色为 \(t_i\)。
我们称一对线段 \(i, j\) 是不好的,当且仅当以下两个条件同时满足:
- \(t_i \neq t_j\);
- 线段 \([l_i, r_i]\) 和 \([l_j, r_j]\) 相交、相嵌或相切。换句话说,存在这样一个整数 \(x\),使得 \(x \in [l_i, r_i]\) 且 \(x \in [l_j, r_j]\)。
请问最多可以选择给定的这些线段中的多少条,使得选择的线段中没有任何一对线段是不好的。
思路:
这边也是有一个比较NB的“贪心”做法。
先假设所有线段都可以被选中且不冲突,则答案为 \(n\)。然后将所有线段双键值排序(\(r\) 为第一键值),并开两个 \(\texttt{Multiset}\),分别记录颜色为 \(1\) 和 \(2\) 的已经被选中的线段。
枚举到下一个线段(设为 \(P\)),当已选中的所有线段中没有线段与 \(P\) 组成的一对线段是不好的,就直接把 \(P\) 加入到对应的 \(\texttt{Multiset}\) 中。
如果有不好的,则把 \(r\) 在 \(P\) 后的第一个线段(设为 \(Q\))从已选线段中删去,然后答案减一。
问:为什么是减一而不是减二?
答:因为 \(P\) 和 \(Q\) 中还可以选出一个,本质上相当于是Ans = Ans - 2 + 1,化简成为Ans --。
代码:
#include <bits/stdc++.h>
#define Maxn 200005
using namespace std;
int n, ans;
multiset<int> st[2];
struct Segment {
int l, r, t;
bool operator <(const Segment &a) const {
return ((r != a.r) ? (r < a.r) : (l < a.l));
}
} p[Maxn];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n, ans = n;
for (int i = 1; i <= n; i ++) {
cin >> p[i].l >> p[i].r >> p[i].t;
p[i].t %= 2;
} sort(p + 1, p + n + 1);
for (int i = 1; i <= n; i ++) {
if (st[!p[i].t].lower_bound(p[i].l) == st[!p[i].t].end()) {
st[p[i].t].insert(p[i].r);
} else {
st[!p[i].t].erase(st[!p[i].t].lower_bound(p[i].l));
ans --; // ans = ans - 2 + 1
}
} cout << ans;
return 0;
}

浙公网安备 33010602011771号