Problem - D - Codeforces
给定一个由n个线段组成的数组[[l1,r1],[l2,r2],…,[ln,rn]],其中每个线段用左右端点表示。如果存在至少一个x满足l1≤x≤r1且l2≤x≤r2,则称线段[l1,r1]和[l2,r2]相交。
如果k为偶数,并且可以将该数组的元素分成k/2对,使得:
每个数组元素都属于恰好一对; 每对中的线段彼此相交; 不同对之间的线段互不相交。
则称该线段数组为beautiful。例如,线段数组[[2,4],[9,12],[2,4],[7,7],[10,13],[6,8]]就是beautiful的,因为可以以以下方式形成3对:
第一个元素(线段[2,4])和第三个元素(线段[2,4]); 第二个元素(线段[9,12])和第五个元素(线段[10,13]); 第四个元素(线段[7,7])和第六个元素(线段[6,8])。
可以看到,每对中的线段相交,不同对之间的线段不相交。
你需要从该数组中删除尽可能少的元素,使得剩余的线段数组beautiful。
输入格式 第一行包含整数t(1≤t≤1000) —— 测试用例数。
每个测试用例包含两行,第一行是整数n(2≤n≤2000),表示数组中线段的个数。接下来n行,每行包含两个整数li和ri(0≤li≤ri≤109),表示线段的左右端点。
输入数据保证所有测试用例中n的总和不超过2000。
输出格式 对于每个测试用例,输出一个整数——你需要删除的最小元素数量,使得剩余的线段数组beautiful。
Example
Input
Copy
3
7
2 4
9 12
2 4
7 7
4 8
10 13
6 8
5
2 2
2 8
0 10
1 2
5 6
4
1 1
2 2
3 3
4 4
Output
Copy
1 3 4
题解:
写本题前,我们要知道一个知识点
[区间问题] 最大不相交区间数量(区间问题+贪心)
[区间问题] 最大不相交区间数量(区间问题+贪心)_Ypuyu的博客-CSDN博客
我们可以把符合条件的区间合并为1个,接着求这么多区间里面,最大不相交区间数量
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> PII;
typedef unsigned long long ULL;
const int N = 4e6 + 10;
int mod = 1e9 + 7;
struct node
{
int l,r;
}a[N],b[N];
bool cmp(node a,node b)
{
if(a.r == b.r)
return a.l < b.l;
return a.r < b.r;
}
void solve()
{
int n;
cin >> n;
for(int i = 1;i <= n;i++)
{
cin >> a[i].l >> a[i].r;
}
sort(a + 1,a + 1 + n,cmp);
int cnt = 0;
for(int i = 1;i <= n;i++)
{
for(int j = i + 1;j <= n;j++)
{
if(a[i].r >= a[j].l)
{
b[++cnt] = {min(a[j].l,a[i].l),max(a[j].r,a[i].r)};
}
}
}
sort(b + 1,b + 1 + cnt,cmp);
int ans = 0;
if(cnt)
ans++;
int r = b[1].r;
for(int i = 2;i <= cnt;i ++)
{
if(b[i].l > r)
{
ans++;
r = b[i].r;
}
}
cout << n - ans*2 <<"\n";
}
signed main()
{
ios::sync_with_stdio(0 );
cin.tie(0);cout.tie(0);
int t = 1;
cin >> t;
while(t--)
{
solve();
}
}