#345 Div2 D. Image Preview

来源:互联网 发布:node forever log 编辑:程序博客网 时间:2024/05/24 03:20

题意:共1<=n<=5e5个照片,从第一个照片开始显示,看一张照片需要1 second,翻到左边或者右边的照片需要1<=a<=1000 second,如果这张照片是'w’状态即水平的时候需要花费1<=b<=1000 second旋转过来再看,翻到已经看过的照片不需要翻转也不需要重复看,不允许跳过没有看过的照片,问1<=T<=1e9 秒最多可以看多少照片;

链接:http://codeforces.com/contest/651/problem/D

一开始没有理解题意,都怪自己英语太渣渣了快哭了

思路:共500000张照片,允许复杂度为O(n*logn);可以想到想某一方向走到水平照片且翻转照片代价较大的时候,可能存在反方向到第n-1,第n-2....但是不可能一张照片经过第三次,这样就不是最优解了。所以可能是先向左走在折返向右,或者先向右走再折返向左;

先向左枚举折返点,然后向右二分寻找最左边的点;再向右枚举折返点,然后二分寻找最左边的点;

注意二分寻找的边界,不能与所枚举的点所代表的数列有重合;

时间复杂度为O(n*logn)

我的代码:

#include <iostream>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <math.h>#include <queue>#include <algorithm>#define N 500050using namespace std;int n,a,b,t;char ma[N];int sum[N];int dsum[N];int ans,maxx;int main(){    int i,j;    while(~scanf("%d%d%d%d",&n,&a,&b,&t)){        scanf("%s",ma);        memset(sum,0,sizeof(sum));        if(ma[0]=='w')            sum[0]=b+1;        else sum[0]=1;        for(i=1;i<n;i++){            sum[i]=sum[i-1]+a+1;            if(ma[i]=='w')                sum[i]+=b;        }        if(ma[n-1]=='w')            dsum[n-1]=a+b+1;        else dsum[n-1]=a+1;        for(i=n-2;i>=1;i--){            dsum[i]=dsum[i+1]+a+1;            if(ma[i]=='w')                dsum[i]+=b;        }        if(sum[n-1]<=t){            printf("%d\n",n);            continue;        }        ans=0;        for(i=0;i<n&&sum[i]<=t;i++){            if(sum[i]+a*i<t){                int left=i+1,right=n-1;                int ans2=-1;                while(left<=right){                    int mid=(left+right)>>1;                    if(sum[i]+a*i+dsum[mid]<=t){                        ans2=mid;                        right=mid-1;                    }                    else                        left=mid+1;                }                if(ans2!=-1){                    ans=max(i+1+n-ans2,ans);                }            }            else{                ans=max(ans,i+1);            }        }        for(i=n-1;i>=1&&dsum[i]+sum[0]<=t;i--){            if(dsum[i]+sum[0]+a*(n-i)<t){                int left=1,right=i-1;                int ans2=-1;                while(left<=right){                    int mid=(left+right)>>1;                    if(dsum[i]+sum[mid]+a*(n-i)<=t){                        ans2=mid;                        left=mid+1;                    }                    else                        right=mid-1;                }                if(ans2!=-1){                    ans=max(n-i+ans2+1,ans);                }            }            else{                ans=max(ans,n-i+1);            }        }        printf("%d\n",ans);    }    return 0;}
1 0
原创粉丝点击