区间覆盖
-
题意:
数轴上有 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
-
解题思路:
结构体node存储区间两个端点x和y,按照较小的端点x升序排列。首先区间覆盖需要满足从1开始,故先对第一个区间进行判断,若x值大于1则不满足条件,直接输出-1。定义变量len记录已经遍历过并被选中的区间端点的最大值,初始状态计数器count值为1,len值为第一个区间的y值,从第二个区间开始遍历,每次循环首先判断是否已经满足覆盖条件,若满足直接跳出循环,输出count。若不满足,判断下一个区间是否满足x值小于等于len+1同时y值大于len,若满足则记录该区间的y值maxlen,再从该区间向后遍历,如果还有其他满足条件且y值大于maxlen的,更新len值,若没有则直接更新len值,每更新一次计数器count加一。
注意:不能直接更新len的原因,
例:
3 10
1 5
4 8
6 10
若直接更新会导致区间(4,8)被选中,最终输出结果为3,显然结果错误。故应在(4,8)被选中时继续向后遍历查找有没有更优区间,即(6,10),若存在则直接更新len的值为10,否则会导致多选中不必要的区间,结果出错。 -
代码实现:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
struct node
{
int x,y;
}a[30000];
bool cmp(node a,node b)
{
if(a.x!=b.x)
return a.x<b.x;
else
return a.y>b.y;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int m,n;
cin>>m>>n;
int c,d;
for(int i=1;i<=m;i++)
{
cin>>c>>d;
a[i].x=c;
a[i].y=d;
}
sort(a+1,a+m+1,cmp);
if(a[1].x>1)
{
cout<<-1<<endl;
}
else
{
int count=1;
int len=a[1].y;
for(int i=2;i<=m;i++)
{
if(len>=n)
{
break;
}
if(a[i].x<=len+1&&a[i].y>len)
{
int maxlen=a[i].y;
for(int j=i;j<=m;j++)
{
if(a[j].x<=len+1)
{
if(a[j].y>maxlen)
{
maxlen=a[j].y;
i=j;
}
}
else
break;
}
len=maxlen;
count++;
}
}
if(len<n)
cout<<-1<<endl;
else
cout<<count<<endl;
}
}