#345 Div2 D. Image Preview

題意:共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 500050
using 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章