大致题意:
在N个时间段中有M个任务,每个任务有一个开始时间和持续时间,当一个有任务的时间段尼克为空闲状态时,他必须进行当前的任务,如果有多个任务,他可以选择任意一个。求他能空闲的最大值。
N,M<=1e4
状态:
由于如果从前往后设置状态,那么会有后效性,所以我们只需从后往前设置即可,即f[i]表示i到N可以获得的最大空闲值。
那么如果当前时间段没有任务时,f[i]=f[i+1]+1;有任务时就是f[i]=max(f[i],f[a[i].start+a[i].last]).那么最终结果就是f[1].
代码如下:
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=10010,M=10010;
struct time{
int st,la;
}a[M];
int f[N],n,m;
int read() {
int S=0,F=1;char C=getchar();
for(;C<'0' || C>'9';C=getchar())
if(C=='-') F=-1;
for(;C>='0' && C<='9';C=getchar())
S=(S<<3)+(S<<1)+C-48;
return S*F;
}
bool cmp(time xx,time yy) {
return xx.st>yy.st;
}
int main() {
n=read(),m=read();
for(int i=1;i<=m;i++) a[i].st=read(),a[i].la=read();
sort(a+1,a+m+1,cmp); //因为需从大到小设置状态,所以需要从大到小排序.
int now=1;
for(int i=n;i;i--)
if(a[now].st!=i)
f[i]=f[i+1]+1;
else
for(;i==a[now].st;)
f[i]=max(f[i],f[a[now].st+a[now].la]),now++;
printf("%d\n",f[1]);
return 0;
}
复杂度为O(n(+常数)).