Chiaki has n intervals and the i-th of them is [li, rj]. She wants to delete some intervals so that there does not exist three intervals a, b and c such that a intersects with b, b intersects with c and c intersects with a.
Chiaki is interested in the minimum number of intervals which need to be deleted.
Note that interval a intersects with interval b if there exists a real number x such that la ≤ x ≤ ra and lb ≤ x ≤ rb .
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains an integer n (1 ≤ n ≤ 50000) – the number of intervals.
Each of the following n lines contains two integers li and ri (1 ≤ li < ri≤ 109) denoting the i-th interval. Note that for every 1 ≤ i < j ≤ n, li ≠ lj or ri ≠ rj.
t is guaranteed that the sum of all n does not exceed 500000.
Output
For each test case, output an integer m denoting the minimum number of deletions. Then in the next line, output m integers in increasing order denoting the index of the intervals to be deleted. If m equals to 0, you should output an empty line in the second line.
Sample Input
1
11
2 5
4 7
3 9
6 11
1 12
10 15
8 17
13 18
16 20
14 21
19 22
Sample Output
4
3 5 7 10
给一些区间,要求删除最少区间使得任意三个区间互不相交。
首先按照区间的起始位置排序,起始位置相同结束位置升序。然后就可以贪心了!
大致过程如下:
- 按序选取三个区间
- 判断是否三个区间互不相交。如果相交,删除这三个区间里结束位置最晚的那个;如果不相交删除起始位置最靠前的那个。
然后说明一下这个为什么是对的。如果这三个区间是相交的,那么一定有一个区间要被删除,所以我们选择结束时间最晚的,这样删除对后续的影响最小;如果这三个区间不相交,我们也可以证明,后续加入的区间开始,一定大于这三个区间里早开始的区间起点。这一点可以用反正法证明,首先有三个区间A B C,互不相交。因为我们加入的顺序是区间开始的升序,所以现在新加入一个区间X的话,起始位置一定不会小于这三个区间的起始位置。如果新加入的区间起始要小于这三个区间中最早结束区间A的终点,所以A的终点小于BC的终点,因为新加入的区间X起点要大于BC的起点,又因为A的终点小于BC的终点,所以区间ABC三个两两之间交集不为空,与原设定不符,故X起点一定大于A的终点,也就是说,区间X的加入不再影响区间A。
#include <stdio.h>
#include <climits>
#include <cstring>
#include <time.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <vector>
#include <string>
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return
#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
struct Interval{
int num;
int left,right;
};
Interval interval[50005];
priority_queue<int,vector<int> ,greater<int> > Q;
inline bool cmp(const Interval &a,const Interval &b);
inline bool judge(Interval *arr);
inline bool intersect(const Interval &a,const Interval &b);
inline int max(Interval *arr);
inline int min(Interval *arr);
int main(){
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--){
int N;
cin>>N;
rep(i,0,N){
interval[i].num=i+1;
cin>>interval[i].left>>interval[i].right;
}
sort(interval,interval+N,cmp);
int pos=0,index;
Interval store[3];
for(;pos<3;pos++){
store[pos]=interval[pos];
}
while(pos<N){
if(judge(store)){//is intersect
index=max(store);
Q.push(store[index].num);
}else{//not intersect
index=min(store);
}
store[index]=interval[pos];
pos++;
}
if(judge(store)){
Q.push(store[max(store)].num);
}
cout<<Q.size()<<"\n";
while(!Q.empty()){
cout<<Q.top()<<" ";
Q.pop();
}
cout<<"\n";
}
re 0;
}
inline bool cmp(const Interval &a,const Interval &b){
if(a.left==b.left)
re a.right<b.right;
re a.left<b.left;
}
inline bool judge(Interval *arr){
Interval &a=arr[0];
Interval &b=arr[1];
Interval &c=arr[2];
bool A_B=intersect(a,b);
bool A_C=intersect(a,c);
bool B_C=intersect(b,c);
if(A_B && A_C && B_C)
re true;
else
re false;
}
inline bool intersect(const Interval &a,const Interval &b){
if( (a.left<=b.right && b.right<=a.right) || (b.left<=a.right && a.right<=b.right))
re true;
else
re false;
}
inline int max(Interval *arr){
int maxn=INT_MIN;
rep(i,0,3){
maxn=max(arr[i].right,maxn);
rep(i,0,3)
if(arr[i].right==maxn)
re i;
}
inline int min(Interval *arr){
int minn=INT_MAX;
rep(i,0,3)
minn=min(minn,arr[i].right);
rep(i,0,3)
if(minn==arr[i].right)
re i;
}