cf#345-D - Image Preview-二分

【题意】

给出n,a,b,T

 有n张照片,拼成一个环。 

1与n是连在一起的。

每次看照片可以向左或向右滑动。

当遇到看过的照片可以跳过【查看时间耗费0秒,移动时间不变】,没看过的不能跳过


现在看的照片是照片1,每次看一张【新】照片,需要花1秒概览,然后如果这个照片是水平的,需要旋转,花费b时间,否则直接花0秒看完 

也就是每次花pay=b+1或 pay=1。

移动到下一张花费是a

T时间内,求最多看多少张


。。一开始看错题,不知道是个环...直接贪心就是了。。。。。后来才知道原来是个环,,这英语翻译水平真是。。。。


是个环也没关系,显然从1开始一直往左看,答案必然是【看到时间耗尽】或【在某个点中途折回往另一个方向看】

当然折回一次就够了,再折回就是浪费移动的时间了

一开始往左:

直接预处理 看到 1-n时所花费的时间ll[i],同理预处理出,从n开始往右走所花费的总时间rr[i],显然rr[]是递增的

然后  枚举每个ll[i],每次  当ll[i]+【折回到1的时间】<=T,时,二分在rr[]中找到能继续走的最远距离,并更新答案。

还有一种情况是一开始往右:

处理方式同上,注意,第一张照片一定先被看过。。。



nlogn

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;

const double pi=acos(-1.0);
double eps=0.000001;  

char tm[500005];
__int64 ll[500005];
__int64 rr[500005];

int main()
{ 
	__int64 n,a,b,t;
	scanf("%I64d %I64d %I64d %I64d",&n,&a,&b,&t);
	scanf("%s",tm+1);
	__int64 tmp=t;
	__int64 pay;
	__int64 i;
	
	__int64 maxx=0;
	for (i=1;i<=n;i++)
	{
		if (tm[i]=='w') pay=b+1; 
		else pay=1;
		if (tmp>=pay) tmp-=pay;
		else break;
		ll[i]=t-tmp;
		if (tmp<a) {i++;break;}
		tmp-=a;
	} 
	for (;i<=n;i++)
		ll[i]=1e9+1;<span style="white-space:pre">		</span>//哨兵

	tmp=t;
	for (i=n;i>=1;i--)
	{ 
		if (tm[i]=='w') pay=b+1; 
		else pay=1;
		if (tmp>=pay) tmp-=pay;
		else break;
		rr[n-i+1]=t-tmp;
		if (tmp<a) {i--;break;}
		tmp-=a;
	} 
	
	for (;i>=1;i--)
		rr[n-i+1]=1e9+1;
	for (i=1;i<=n; i++)
	{
		if (ll[i]==1e9+1)break;
		if (t-ll[i]>a*i )
		{ 
				__int64 it=upper_bound(rr+1,rr+1+n,t-ll[i]-a*i)-rr;
				  it--;
			if (it+i>maxx) maxx=i+it;
		}
		if (t-ll[i]>=0)
		if (i>maxx) maxx=i;

	}
<span style="font-size: 18.5714px; font-family: Arial, Helvetica, sans-serif;">//第二种情况,先右再左</span>
	for (i=1;i<=n;i++)
	{
		if (rr[i]==1e9+1) break;
		else
			rr[i]+=a;<span style="white-space:pre">		</span>//加上从1到n的时间
	}
	t-=ll[1];<span style="white-space:pre">				</span>//一定先看第一张
	for (i=1;i<=n; i++)
	{
		if (rr[i]==1e9+1)break;
		if (t-rr[i]>a*(i) )
		{ 
				__int64 it=upper_bound(ll+2,ll+1+n,t-rr[i]-a*(i)+ll[1])-ll;
				  it--;
			if (it+i>maxx) maxx=i+it;
		}
		if (t-rr[i]>=0)
		if (i+1>maxx) maxx=i+1;<span style="white-space:pre">	</span>//第一张也被看了,所以是it+1张

	}
	if (maxx>n) maxx=n;
	printf("%I64d\n",maxx);
	
	return 0;
}




在看的照片是照片1。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值