AcWing 907 区间覆盖

题目描述:

给定N个闭区间[ai,bi]以及一个线段区间[s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。

输出最少区间数,如果无法完全覆盖则输出-1。

输入格式

第一行包含两个整数s和t,表示给定线段区间的两个端点。

第二行包含整数N,表示给定区间数。接下来N行,每行包含两个整数ai,bi,表示一个区间的两个端点。

输出格式

输出一个整数,表示所需最少区间数。

如果无解,则输出-1。

数据范围

1≤N≤10^5,
−10^9≤ai≤bi≤10^9,
−10^9≤s≤t≤10^9

输入样例:

1 5
3
-1 3
2 4
3 5

输出样例:

2

分析:

我们先对区间按左端点从小到大排序,然后遍历区间。在所有左端点不大于s的区间中选择右端点最大的那个区间,设选择的区间为[l1,r1],则[s,r1]已经被覆盖了,更新需要被覆盖区间的起点s = r1,继续遍历区间,再次找到所有左端点不大于s的区间中右端点最大的区间,重复该过程直至更新后的s超过了终点t。由于每次选择的都是所有合法区间中能够覆盖[s,t]中尚未被覆盖区间最长的区间,所以显然最后选择的区间数是最少的。

我们在遍历区间的过程中,只有遍历到了左端点超过s的区间才知道之前小于s的区间已经遍历完了,此时才能更新s,并且需要将指针回退一格以便循环继续。几种不能覆盖给定区间的情况是:其一,左端点小于s的区间中最大的右端点也小于s,所以不能覆盖s;其二,区间中找不到小于s的左端点,也不能覆盖s。

#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100005;
typedef pair<int,int> pii;
pii a[maxn];
int main(){
    int l,r,n;
    cin>>l>>r;
    cin>>n;
    for(int i = 0;i < n;i++)    cin>>a[i].first>>a[i].second;
    sort(a,a + n);
    int t = -2e9,res = 0;
    for(int i = 0;i <= n;i++){
        if(i == n || a[i].first > l){//遍历到了左端点超过s的区间或者遍历到了最后一个区间
            if(t == -2e9 || t <= l) break;//最小的左端点大于s或者选择区间的右端点小于s
            l = t,t = -2e9,i--,res++;//指针回退一格
            if(i == n - 1)  break;//区间遍历完了
        }
        else    t = max(t,a[i].second);//找右端点最大的
        if(l >= r)  break;//已经覆盖了所给区间
    }
    if(l >= r)  cout<<res<<endl;
    else    cout<<"-1"<<endl;
    return 0;
}
发布了272 篇原创文章 · 获赞 26 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_30277239/article/details/104002724