cf#345-D - Image Preview-二分

来源:互联网 发布:中国矿工软件 编辑:程序博客网 时间:2024/06/04 08:04

【题意】

给出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;elserr[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
原创粉丝点击