[codeforces721E]Road to Home

来源:互联网 发布:手机相贯线软件 编辑:程序博客网 时间:2024/05/21 04:39

【题目大意】

有一条长为l的公路(可看为数轴),n盏路灯,每盏路灯有照射区间且互不重叠,有个人要走过这条公路,他只敢在路灯照射的地方唱歌,固定走p唱完一首歌,歌曲必须连续唱否则就要至少走t才能继续唱,按序给出路灯照射范围

【解题思路】

简单可证对于一段照射区间要么不唱歌要么能唱多久唱多久

DP,f[i]表示前i段最多能唱几首歌,g[i]表示在唱f[i]首歌的情况下最早在什么时候可以停止唱歌

m=(r[i]-max(g[j]+t,l))/p

f[i]=max(f[j]+m)

g[i]=min(g[i],max(g[j]+t,l)+m*p)

因为g[]具有单调性,所以处理i时只要从j(g[j]+t∈[l[i],r[i]))转移就行了,剩下的可以全部通过f[i]=max(f[i],f[i-1])快速转移

时间复杂度O(N)

【一段废话】

题目看完感觉应该是dp,然后就开始找单调性,结果越想越复杂,思路还一直被这题的其中一个tag“二分”带跑,然后看完题解后感觉自己简直智障,哎,果然智商低的人是做不了OI的

【呆马】

#include<cstdio>#include<algorithm>#include<cmath>#include<cstdlib>#include<iostream>using namespace std;int l,n,p,t,i,j,x,y,v,L,f[100001],g[100001];int main(){scanf("%d%d%d%d\n",&l,&n,&p,&t);g[0]=-t;for (i=j=1;i<=n;i++){scanf("%d%d\n",&x,&y);j--;for (;j<i && g[j]+t<=y;j++){L=max(x,g[j]+t);v=(y-L)/p+f[j]; if (v>f[i] || (v==f[i] && L+(y-L)/p*p<g[i])) f[i]=v,g[i]=L+(y-L)/p*p;}if (f[i-1]>f[i] || (f[i-1]==f[i] && g[i-1]<g[i])) f[i]=f[i-1],g[i]=g[i-1];}printf("%d",f[n]);}


0 0
原创粉丝点击