一、问题描述
数轴上有 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
二、思路概述
先将区间按照先按a升序,再按b升序的顺序进行排序。
对区间进行遍历:
(1)如果此时的区间能够覆盖住上一个区间,则用此区间替代上一个区间,
(2)若此时的区间能被上一个区间所覆盖,则不做改变
(3)若此时的区间的头和尾都比上一个区间靠后,则可选择这个区间,继续往下判断。
(4)还有其他的情况,是全部的区间无法覆盖[1,t]范围,只能返回“-1”。
三、注意点
1.由于算法本身的问题,计数器应该从1开始,才能输出正确答案,这一点要注意。
2. 这道题输入数据很多,使用scanf而不是cin。
四、完整代码
#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
struct Inter
{
int a,b;//左右端点
};
int cmp(Inter x,Inter y)
{
if(x.a!=y.a)return x.a<y.a;//先按a升序
return x.b<y.b;//再按b升序
}
void Sum(Inter *ter,int n,int t)//计算的函数
{
if(ter[0].a>1){printf("%d",-1);return;}
int start=1;
int end=1;
int sum=1;
for(int i=0;i<n;i++)
{
if(ter[i].a<=start&&ter[i].b>end)
{
end=ter[i].b;//此时用第i个区间代替上面的区间
}
if(ter[i].a>start&&ter[i].b>end)
{
if(ter[i].a>end+1)
{
printf("%d",-1);return;//区间中间断了,
}
sum=sum+1;
start=end+1;
i=i-1;
}
if(end>=t)
break;
}
if(end<t)
printf("%d",-1);
else
printf("%d\n",sum);
}
int main()
{
int n,t;
scanf("%d%d",&n,&t);
Inter *ter=new Inter[n];//数组用来存储n个区间
for(int i=0;i<n;i++)
{
scanf("%d%d",&ter[i].a,&ter[i].b);
}
sort(ter,ter+n,cmp);//排序,预处理
Sum(ter,n,t);
delete []ter;
return 0;
}