题解: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
直接看评测结果,比如我。