阿生在进行一场5v5王者竞技游戏,但遗憾的是阿生被对面针对了,对方打野疯狂针对他,导致他不得不点亮整个河道来确保自身的安全,阿生的游戏体验就寄托在能否能获得一条长度为L的河道的全部视野,即可以看作是[0,L]的一条数轴。
游戏当中有n个可以提供视野的真视守卫,第i个真视守卫能够覆盖区间[xi,yi]。现在阿生想知道至少用几个真视守卫就可以覆盖整个河道来保证自己的游戏体验。
输入格式:
输入包括n+1行。
第一行包括两个正整数n和L(1<=n<=105,1<=L<=109)
接下来的n行,每行两个正整数xi,yi(0<=xi<=yi<=109),表示第i个真视守卫覆盖的区间。
输出格式:
一个整数,表示最少需要的真视守卫数量, 如果无解, 输出-1。
输入样例:
在这里给出一组输入。例如:
4 6
5 6
2 4
0 3
4 8
输出样例:
在这里给出相应的输出。例如:
3
思路:区间覆盖板子题,自己仔细想一想
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define endl '\n'
#define rep(i,a,n) for (int i = a; i < n; i ++ )
#define repn(i,a,n) for (int i = a; i <= n; i ++ )
#define pb push_back
#define IOS ios::sync_with_stdio(false); cin.tie(0);cout.tie(0);
typedef long long ll;
#define all(x) (x).begin(),(x).end()
typedef pair<int,int> PII;
ll gcd(ll a,ll b) { return b ? gcd(b,a % b) : a; }
const int mod = 1e9+7;
const int N = 100010;
struct Range{
int l, r;
}range[N];
bool cmp(Range a, Range b){
return a.l < b.l;
}
int n, ed;
int res;
int main()
{
IOS;
cin >> n >> ed;
rep(i, 0, n){
int l, r; cin >> l >> r;
range[i] = {l, r};
}
sort(range, range + n, cmp);
int st = 0;
bool success = false;
for (int i = 0; i < n; i ++ ){
int j = i, r = -2e9;
//如果每次不把r更新为-2e9的话,st和r相等,可能不会出现r<st的情况,如果无法覆盖的话,就会一直循环
while (j < n && range[j].l <= st){ //找到所有左端点小于start的区间中右端点的最大值,选上这个区间
r = max(r, range[j].r);
j ++ ;
}
if(r < st){ //当前右端点的最远位置不能到达下一线段的左端点,一定不能覆盖
res = -1;
break;
}
res++;
if(r >= ed){
success = true; //只有从这个出口出去才被视作成功覆盖
break;
}
st = r; //更新下一次的st,i
i = j - 1;
}
cout << res << endl;
return 0;
}
/*
思路:1.将所有区间按左端点从小到大排序
2.从前往后依次枚举每个区间,在所有能覆盖start(线段区间起点)中,选择右端点最大(最靠右)的区间
选完之后,将start更新成右端点的最大值
可以证明,对于最优解ans,一定可以替换成所求出来的解cnt,即证明了ans == cnt
*/