**
题目描述:
数轴上有 n (1<=n<=25000)个闭区间 [ai, bi],选择尽量少的区间覆盖一条指定线段 [1, t]( 1<=t<=1,000,000)。
覆盖整点,即(1,2)+(3,4)可以覆盖(1,4)。
不可能办到输出-1。
Input:
第一行:N和T
第二行至N+1行:每一行一个闭区间。
Output:
选择的区间的数目,不可能办到输出-1
**
example:
Input:
3 10
1 7
3 6
6 10
Output:
2
个人思路:
沿承了一贯的风格,结构体存储区间端点。首先,在输入数据的时候进行预处理,将在直线外的区间先切掉,其实直线在这里就是一个大的区间[1,t]。之后按照a从小到大排序,然后选择第一个区间,如果第一个区间的左端点 > 1,则无解;否则,选择起点在1的最长区间,然后将其右端点设置成起点s,重复以上步骤。
数据结构:
struct zone {//一个区间
int a, b;
zone() {};//构造函数
zone(int & x,int & y) {//带参数的构造函数
a = x; b = y;
}
bool operator<(const zone& q) const{//重载小于
return a != q.a ? a < q.a : b > q.b;
}
};
zone a_b[100000];
int n, t;//待输入区间数、直线右端
int rt = 0;//起点s
int num = 0;//最小区间个数
在这里重载小于号其实只需要a的升序就可以,至于我还用了b的降序,是因为他每一步要求区间最长,这样第一步可能就会得到最长的,后面只需要执行if语句,而不需要更新变量值了。
**
代码块:
#include<iostream>
#include<algorithm>
using namespace std;
struct zone {
int a, b;
zone() {};
zone(int & x,int & y) {
a = x; b = y;
}
bool operator<(const zone& q) const{
return a != q.a ? a < q.a : b > q.b;
}
};
zone a_b[100000];
int n, t;
int rt = 0;//起点
int num = 0;
int max1(int x, int y) {
if (x >= y)
return x;
else
return y;
}
int main() {
cin >> n >> t;
//int x,y;
for (int i = 0; i < n; ++i){
scanf_s("%d%d", &a_b[i].a, &a_b[i].b);
}
sort(a_b, a_b + n);//排序
if (a_b[0].a > 1) { //如果第一个区间不符合,无解,退出
cout << "-1" << endl;
return 0;
}
int i = 0;//a_b的指针
while (1) {
int nowrt = 0;//当前的起点
int sign = 0;//检查是否中间有间隔
num++;//区间个数++
for (; i < n; ++i) {
if (a_b[i].a <= rt + 1) {//如果左端点 < 起始点(也就是没有间隔)
nowrt = max1(nowrt, a_b[i].b);//选最长的最为下一个起点
sign = 1;//标记有符合条件的区间
}
else break; //当区间左端点 > 起点
}
if (nowrt >= t) {//当起始点>=终点时,说明已经覆盖
cout << num << endl;
break;
}
if (sign == 0 || i >= n) { //如果中间被隔开了或者区间遍历完毕并且没覆盖直线
cout << "-1" << endl;
break;
}
rt = nowrt;//设置下一个起点
}
return 0;
}
**