【题意】
给出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。