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;
}
posted @ 2024-11-24 16:06  BLM-dolphin  阅读(40)  评论(0)    收藏  举报