尼克的任务

link

题说真的并不难,主要是这道题可以提供一些重要的思想。

一个是关于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;
}
posted @ 2022-06-20 16:28  Feyn618  阅读(29)  评论(0编辑  收藏  举报