尼克的任务
题说真的并不难,主要是这道题可以提供一些重要的思想。
一个是关于DP的顺序。这道题第一反应是用fi来代表前i分钟的最大休息时间,但发现方程似乎不是很好写。究其原因是终点时间不能作为主动决策的依据(毕竟题目说了,当几个时间段起点重合时才可以选择),于是考虑用fi代表时间i到时间m的最大休息时间。
另一个是离散化。虽然这道题用不到,但uoj上的题题目一样,只是扩大了总时间。于是就会发现有许多状态是不必要的,可以用离散化直接干掉,这样虽然多了个log但好写得多。还有就是理论上可以用扫描的方法干掉那个log但我不想写。
放离散化的代码:
#include<bits/stdc++.h>
//#define zczc
const int N=1000010;
using namespace std;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
inline void check(int &s1,int s2){
if(s1<s2)s1=s2;
}
int m,n,cnt,f[N],b[N];
struct node{
int a,b;
}a[N];
inline bool operator <(node s1,node s2){
return s1.a>s2.a;
}
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
read(m);read(n);
for(int i=1;i<=n;i++){
read(a[i].a);read(a[i].b);a[i].b=a[i].a+a[i].b;
b[++cnt]=a[i].a;b[++cnt]=a[i].b;
}
b[++cnt]=1;b[++cnt]=m;
sort(b+1,b+cnt+1);
sort(a+1,a+n+1);
int num=unique(b+1,b+cnt+1)-b-1;
b[num+1]=m+1;
for(int now=1,i=num;i;i--){
//printf("cc:%d\n",b[i]);
if(a[now].a==b[i]){
while(a[now].a==b[i]){
int res=upper_bound(b+1,b+num+1,a[now].b)-b-1;
check(f[i],f[res]);
//printf("kk:%d\n",now);
now++;
}
}
else f[i]=f[i+1]+b[i+1]-b[i];
}
printf("%d",f[1]);
return 0;
}
一如既往,万事胜意