zoukankan      html  css  js  c++  java
  • [Codeforces 721E]Road to Home

    题目大意:有一条长为l的公路(可看为数轴),n盏路灯,每盏路灯有照射区间且互不重叠,有个人要走过这条公路,他只敢在路灯照射的地方唱歌,固定走p唱完一首歌,歌曲必须连续唱否则就要至少走t才能继续唱。问你最多能唱几首歌?

    解题思路:一道dp的题目。

    首先有一个结论:对于一段区间,你能唱几首歌就唱几首歌。

    因为如果你少唱一首歌,在下个区间最多也就多唱一首歌,与你在前面唱这首歌是一样的。

    所以我们设f[i]表示前i个区间最多唱的歌的数量,g[i]表示在f[i]的前提下,最早的停止唱歌的位置。

    很显然有$f[i]=max { f[j]+lfloorfrac{(r[i]-max(g[j]+t,l[i]))}{p} floor }$,$g[i]=min{ r[i]-(r[i]-max(g[j]+t,l[i]))mod p }$        ($j<i$)。

    这样的话时间复杂度就是$O(n^2)$,难以接受。

    注意到f和g都是满足单调性的(f很显然,g的话,总不可能唱第2首歌比唱第1首歌还前面),所以容易想到单调队列。

    这样时间复杂度就优化到$O(n)$。

    具体单调队列的操作详见代码。

    C++ Code:

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    struct Struct{
    	int f,g;
    }q[100005];
    int l,n,p,t,head,tail;
    inline int max(int a,int b){return a>b?a:b;}
    inline int readint(){
    	char c=getchar();
    	for(;!isdigit(c);c=getchar());
    	int d=0;
    	for(;isdigit(c);c=getchar())
    	d=(d<<3)+(d<<1)+(c^'0');
    	return d;
    }
    int main(){
    	l=readint(),n=readint(),p=readint(),t=readint();
    	q[0]=(Struct){0,-0x3f3f3f3f};
    	head=0,tail=0;
    	int ans=0;
    	while(n--){
    		int x=readint(),y=readint();
    		int nans=0,ng=0;
    		head?--head:1;
    		while(head<=tail){
    			if(q[head].g+p+t>y)break;
    			int ff=q[head].f+(y-max(q[head].g+t,x))/p,
    			gg=y-(y-max(q[head].g+t,x))%p;
    			if(ff>nans||ff==nans&&gg<ng)nans=ff,ng=gg;
    			++head;
    		}
    		if(ans<nans){
    			ans=nans;
    			q[++tail]=(Struct){nans,ng};
    		}
    	}
    	return!printf("%d
    ",ans);
    }
  • 相关阅读:
    Js:getAttribute(转)
    javaScript(1):基础部分
    元信息标签<meta>
    HTML补充:引用脚本、特殊符号、标签、元素、多媒体
    .Net Micro Framework研究—让MF支持英文输入法
    .Net Micro Framework研究系列文章
    .Net Micro Framework研究—实现SideShow窗体界面
    .Net Micro Framework研究—MF驱动继电器
    .Net Micro Framework SDK 2.5 发布
    第二十五章补充内容 9 关键字volatile 简单
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/8157677.html
Copyright © 2011-2022 走看看