版权声明:希望能在自己成长的道路上帮到更多的人,欢迎各位评论交流 https://blog.csdn.net/yiqzq/article/details/82118421
原题地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3953
题意:删除最少的区间使得三个区间存在一个不相交的两个区间。
思路:我,们可以先按左端点排序,那么出现三个区间重叠的情况就是出现三个区间的左端点都是来连续,即把三条线段的左右端点全部存进数组,排序之后,左端点都比右端点大.那么每次就取三个区间然后一一判断就行了.
需要注意的是,删除区间的时候删掉的应该是
值最大的,而不是
值最小的.
#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
struct node {
int l, r, id;
node() {}
node(int r, int id): r(r), id(id) {}
} e[maxn];
bool cmp(node a, node b) {
if (a.l == b.l) return a.r < b.r;
else return a.l < b.l;
}
bool cmp2(node a, node b) {
return a.r > b.r;
}
//判断三个集合是否相交
bool solve(node a, node b, node c) {
int f1 = (a.r >= b.l);
int f2 = ((c.l <= a.r) && (c.l <= b.r));
if (f1 && f2) return 1;
else return 0;
}
int t, n;
vector<int>v;
int main() {
scanf("%d", &t);
while (t--) {
v.clear();
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &e[i].l, &e[i].r);
e[i].id = i;
}
if (n <= 2) {
printf("0\n\n");
continue;
}
sort(e + 1, e + 1 + n, cmp);
node x[3];
int ans = 0;
x[0] = e[1];
x[1] = e[2];
for (int i = 3; i <= n; i++) {
x[2] = e[i];
sort(x, x + 3, cmp);
int f = solve(x[0], x[1], x[2]);
sort(x, x + 3, cmp2);
if (f) {
ans++;
v.push_back(x[0].id);//删掉最最右边的,即r值最大的
//因为要形成相交集合是要都小于第一个区间的r值
swap(x[0], x[2]);
}
}
printf("%d\n", ans);
sort(v.begin(), v.end());
if (ans) {
printf("%d", v[0]);
for (int i = 1; i < ans; i++) printf(" %d", v[i]);
}
printf("\n");
}
return 0;
}