ZOJ3953 Intervals 贪心

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

给一些区间,要求删除最少区间使得任意三个区间互不相交。
首先按照区间的起始位置排序,起始位置相同结束位置升序。然后就可以贪心了!
大致过程如下:

  1. 按序选取三个区间
  2. 判断是否三个区间互不相交。如果相交,删除这三个区间里结束位置最晚的那个;如果不相交删除起始位置最靠前的那个。

然后说明一下这个为什么是对的。如果这三个区间是相交的,那么一定有一个区间要被删除,所以我们选择结束时间最晚的,这样删除对后续的影响最小;如果这三个区间不相交,我们也可以证明,后续加入的区间开始,一定大于这三个区间里早开始的区间起点。这一点可以用反正法证明,首先有三个区间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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值