题解:CF1841D Pairs of Segments

题目大意:

给你 \(n\) 条线段,让你删除掉其中的一些线段,使得剩余的线段是偶数且可以两两配对且每组不相交。

解题思路:

正难则反,计算选择多少条可以满足要求。

只有相交的两条线段才可能成为一组,所以枚举两条线段,如果它们相交,直接合并起来。

题目还要求每组线段不相交,所以直接计算合并后的线段最多不相交的数量。

最后用总线段数减去合并后的线段最多不相交的数量即可。

代码:

#include <bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define ldb long double
#define db double
#define endl '\n'
using namespace std;
const int N = 2010;
int read() {
	char c = 0;
	int f = 1, x = 0;
	while (c < '0' || c > '9') {
		if (c == '-')
			f = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9') {
		x = x * 10 + (int)(c - '0');
		c = getchar();
	}
	return f * x;
}
void write(int x) {
	if (x == 0) {
		putchar(x + '0');
		return ;
	}
	if (x < 0) {
		putchar('-');
		x = abs(x);
	}
	stack<int> s;
	while (x) {
		s.push(x % 10);
		x /= 10;
	}
	while (s.size()) {
		putchar(s.top() + '0');
		s.pop();
	}
}
int n;
struct node {
	int x, y;
} a[N], b[N * N];
int len;
bool cmp(node a, node b) {
	return a.y < b.y;
}
int ans, cnt;
void Solve() {
	len = 0;
	n = read();//输入数据
	for (int i = 1; i <= n; i++) a[i].x = read(), a[i].y = read();
	for (int i = 1; i <= n; i++)//枚举线段
		for (int j = i + 1; j <= n; j++) {
			if (a[i].y < a[j].x || a[i].x > a[j].y) continue;
			b[++len] = {min(a[i].x, a[j].x), max(a[i].y, a[j].y)};
		}
	sort(b + 1, b + len + 1, cmp);//计算合并后的线段最多不相交的数量
	ans = 0;
	cnt = -1;
	for (int i = 1; i <= len; i++)
		if (b[i].x > cnt) {
			cnt = b[i].y;
			ans += 2;
		}
	cout << n - ans << endl;
}
signed main() {
	int t = 1;
	t = read();
	while (t--) Solve();
	return 0;
}

通过记录

最后一句话:如果你在洛谷上总是 UKE,建议到 Codeforces 直接看评测结果,比如我

posted @ 2024-10-25 11:03  zla_2012  阅读(4)  评论(0编辑  收藏  举报