描述
数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t]( 1<=t<=1,000,000)。
覆盖整点,即(1,2)+(3,4)可以覆盖(1,4)。
不可能办到输出-1
输入
第一行:N和T
第二行至N+1行: 每一行一个闭区间。
输出
选择的区间的数目,不可能办到输出-1
样例输入
3 10
1 7
3 6
6 10
样例输出
2
提示
这道题输入数据很多,请用scanf而不是cin
分析:为了覆盖所有区间,需要找到左端点最小的点,那么区间按照左端点排序,从小到大。考虑前面k个区间与最优解一样,选下个区间要考虑左端点在last区间的右端点的左边(这个左边具体来说就是cur<=last+1,因为区间是左右闭合的),找到所有这些点,再找到右端点最大的。
代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<pair<int, int>> seg;
bool cmp_1(pair<int, int> a, pair<int, int> b)
{
return a.first < b.first;
}
bool cmp_2(pair<int, int> a, pair<int, int> b)
{
return a.second > b.second;
}
int find_max(int a, int b)
{
int max = 0;
int x;
for (int i = a; i <= b; i++)
{
if (seg[i].second > max)
{
max = seg[i].second;
x = i;
}
}
seg.erase(seg.begin() + x);
return max;
}
int main()
{
int N, T;
cin >> N >> T;
for (int i = 0; i < N; i++)
{
int a, b;
cin >> a >> b;
seg.push_back(pair<int, int>(a, b));
}
sort(seg.begin(), seg.end(), cmp_1);
int cnt = 0;
int cur = 0;
int i = 0;
while(1)
{
bool flag = false;
while (i < seg.size() && seg[i].first <= cur + 1)
{
i++;
flag = true;
}
if (!flag)
{
cout << -1;
return 0;
}
i--;
cur = find_max(0, i);
cnt++;
if (cur >= T)
{
cout << cnt;
return 0;
}
}
}