目录
问题描述
大表哥分配 N (1 <= N <= 25,000) 只中的一些奶牛在牛棚附近做些清洁。 他总是要让至少一只牛做清洁。他把一天分成T段(1 <= T <= 1,000,000), 第一段是1,最后一段是T
每只奶牛只在一些时间段有空。奶牛如果选择某一段时间,则必须完成整段时间的工作
你的任务是帮助FJ安排一些奶牛,使每段时间至少有一只奶牛被安排来做这件事。并且奶牛数应尽可能小。如果不可能办到,输出-1
Input
注意,输入包含多组测试数据,请处理到文件结束
第一行:N和T
第二行至N+1行: 每一行一个闭区间,表示奶牛工作的开始时间和结束时间。
Output
选择的区间的数目,不可能办到输出-1
Sample Input
3 10
1 7
3 6
6 10
Sample Output
2
提示
这道题输入数据很多,请用scanf而不是cin
解题思路
问题分析
首先分析这是一个什么问题,题目要求选择最少的区间来覆盖 这个区间,这个题可以使用区间dp+线段树来做(大材小用,区间dp+线段树可以解决每个区间花费不同的区间最小花费问题,用在这里自然可以),但是更好的算法应该还是贪心。
注意坑点
和 是可以覆盖 的。
贪心策略
我们先考虑按照区间的左端点从小到大排序,为什么这么排呢?因为我们要让奶牛覆盖完整的区间,那么肯定先选能够在1节点工作的奶牛,假设这个奶牛工作的区间是 ,那么下一个要选的奶牛,就是从 开始,工作时间最久的(假设其工作区间是 ),也就是需要 (+1是因为我们上面提到的坑点)。由于我们开始是按照区间的左端点从小到大排序,那么从循环开始,后面连续一段应该都是 的(如果没有,设个标记直接跳出,因为没有办法完全覆盖了),然后用while处理找工作时间最长的即可。更多详细信息见下方代码。
完整代码
//#pragma GCC optimize(2)//比赛禁止使用!
//#pragma G++ optimize(2)
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn=25000+1;
struct Interval
{
int a,b;
}len[maxn];
int n,t,ans;
bool comp(Interval a,Interval b)//a小的排在前面
{
return a.a<b.a;
}
int getint()
{
int x=0,s=1;
char ch=' ';
while(ch<'0' || ch>'9')
{
ch=getchar();
if(ch=='-') s=-1;
}
while(ch>='0' && ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*s;
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
n=getint(); t=getint();
for (int i=1; i<=n; i++)
len[i].a=getint(),len[i].b=getint();
sort(len+1,len+1+n,comp);
int temp=0;//初始值赋为0,可以在后面的循环中观察有无奶牛早早去工作(不赋为1是为了在后面的while中加了1
int tempmax=INT_MIN;
int id=0;
bool flag=false;//用于判断是否全部覆盖
for (int i=1; i<=n; i++)
{
flag=false;
while(len[i].a<=temp+1 && i<=n)//这段区间可以作为备选利用就进入循环,此处加一很关键,因为(1,2),(3,4)算覆盖了(1,4)
{
flag=true;//flag=true保证所有区间都可以覆盖上
if(len[i].b-temp>tempmax)//选从temp开始工作时间最长的
{
tempmax=len[i].b-temp;
id=i;//记录这个从temp开始工作时间最长的奶牛
}
i++;
}
if(!flag) break;//找不到可以利用的区间,覆盖失败,直接跳出
ans++;
i--;//如果进入了循环,最后多加了一次
temp=len[id].b;//选中的节点取从上一个节点开始工作时间最长的
if(temp>=t) break;//已经找到足够的奶牛,直接跳出
tempmax=INT_MIN;
}
if(!flag || temp<t) printf("-1\n");
else printf("%d\n",ans);
return 0;
}
部分易错数据
Input1
4 100
21 50
50 81
1 20
80 99
Output1
-1
Input2
3 10
1 3
4 6
7 10
Output2
3
Input3
3 10
2 4
3 7
6 10
Output3
-1