Codeforces 650B 二分

题目:http://codeforces.com/problemset/problem/650/B
题意:
:给n张图片循环可看,每张图片的朝向为横(w)|竖(v),但是手机是竖直放置的。开始时打开的是第0张图片,如果一张图片为w放置就需先花b秒边把该张图片变成v朝向,从一张图片到下一张图片手机的反应时间为a秒,每观察一张图片需要1秒钟。不能直接跳过没看的图片,但是重新刷到看过的图片时,所花的时间只是手机的反应时间,不复看;问在t秒内能看的最多图片的数目为多少?
分析:
考虑一下什么时候会出现最优解,一定是往左翻x个,再往右翻y个,不会出现来回翻的情况,所以可以二分答案,算出往先左耗时和返回再往右耗时与先往右再往左耗时最小值是否在T限制内。这样的方法是比较简单的。看到还有人是暴力枚举左边可以看几个,然后二分右边,与暴力枚举右边再二分左边去找最大值,这样也是可行的。在实现方式上,看到有的人扩展了数组,可以很方便的枚举,可以学习一下:http://www.cnblogs.com/hxer/p/5265612.html

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5;
int n,a,b,t;
ll w[N];
char s[N];
bool check(int m)
{
    for(int i=1;i<=m;i++){
        ll sum1=w[i]+(w[n]-w[n-(m-i)]);
        ll sum2=min((i-1)*a*2+(m-i)*a,(i-1)*a+(m-i)*a*2);
        if(sum1+sum2<=t)return 1;
    }
    return 0;
}
int main()
{
    scanf("%d%d%d%d%s",&n,&a,&b,&t,s+1);
    for(int i=1;i<=n;i++)w[i]=w[i-1]+1+(s[i]=='w'?b:0);
    int l=0,r=n;
    while(l<r){
        int m=(l+r+1)>>1;
        if(check(m))l=m;
        else r=m-1;
    }
    printf("%d\n",l);
}
posted @ 2016-03-28 22:28  HARD_UNDERSTAND  阅读(170)  评论(0编辑  收藏  举报