题意
数轴上有 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)把所有区间按照左端点从小到大、右端点从大到小排序;
2)对于第一个区间必须有,左端点<=1;
3)因为要使区间数尽量少所以选取的区间要尽量长,在同起点的情况下,择选右端点最大的区间;
4)在第一个区间选出后,将此区间右端点+1作为新要选择的区间的左端点,之后重复选择相应的最长区间,直到区间右端点数>=t为止
总结
先前提交了 六次,一直WA,主要错误有以下两点:
1)在选取最长区间时,我默认了起点为1的区间只有一个,而忘记了起点为1的区间也需要甄选出最长的;
2)我将lasty>=t输出ans的判断条件加在了程序最后,但我没有意识到在每一次的for循环最后都会有一个判断lasty>=t,条件满足即马上跳出,不需要继续。
else
{
for(int i=0;i<n;i++)
{
if(ite[i].x<=lastx)//选取起点<=lastx的最长区间
lasty=max(lasty,ite[i].y);
if(ite[i].x>lastx)
{
ans++;
lastx=lasty+1;//新起点为上一个区间尾+1
if(ite[i].x<=lastx)//选取起点<=lastx的最长区间
lasty=max(lasty,ite[i].y);
else
{
cout<<"-1"<<endl;//接不上
goto mark;
}
}
if(lasty>=t)
{
cout<<ans<<endl;
goto mark;
}
}
if(lasty<t) cout<<"-1"<<endl;
}
mark:
代码
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=26000;
struct iteval
{
int x,y;//左右开区间端点
}ite[maxn];
bool cmp(iteval a,iteval b)
{
if(a.x!=b.x) return a.x<b.x; //先按左端点从小到大排序
else return a.y>b.y; //左端点相同的按照右端点从大到小排序
}
int main()
{
int n,t;
scanf("%d%d",&n,&t);
for(int i=0;i<n;i++)
scanf("%d%d",&ite[i].x,&ite[i].y);
sort(ite,ite+n, cmp); //区间排序
int ans=1;//记录选中区间个数
int lastx=1;
int lasty=ite[0].y;
if(ite[0].x>1)
{
cout<<"-1"<<endl;
}
else
{
for(int i=0;i<n;i++)
{
if(ite[i].x<=lastx)//选取起点<=lastx的最长区间
lasty=max(lasty,ite[i].y);
if(ite[i].x>lastx)
{
ans++;
lastx=lasty+1;//新起点为上一个区间尾+1
if(ite[i].x<=lastx)//选取起点<=lastx的最长区间
lasty=max(lasty,ite[i].y);
else
{
cout<<"-1"<<endl;//接不上
goto mark;
}
}
if(lasty>=t)
{
cout<<ans<<endl;
goto mark;
}
}
if(lasty<t) cout<<"-1"<<endl;
}
mark:
return 0;
}