1. 程式人生 > >BZOJ 4590: [Shoi2015]自動刷題機

BZOJ 4590: [Shoi2015]自動刷題機

思路 else enter 最大 zoj 發現 目的 ont 自信

4590: [Shoi2015]自動刷題機

Description

曾經發明了信號增幅儀的發明家SHTSC又公開了他的新發明:自動刷題機--一種可以自動AC題目的神秘裝置。自動 刷題機刷題的方式非常簡單:首先會瞬間得出題目的正確做法,然後開始寫程序,每秒,自動刷題機的代碼生成模 塊會有兩種可能的結果: A.寫了x行代碼。 B.心情不好,刪掉了之前寫的y行代碼。(如果y大於當前代碼長度則相當於全部刪除。) 對於每個OJ所有題目,存在某個固定的長度n>0。一旦自動刷題機在某秒結束時積累了大於等於n行的代碼,它就會 自動提交並AC此題,然後新建一個文件開始寫下一題。SHTSC在某個OJ上跑了一天的自動刷題機,得到了很多條關 於寫代碼的日誌信息。他突然發現自己沒有記錄這個OJ的n究竟是多少。所幸他通過自己在OJ上的Rank知道了機一 共切了k道題。希望你計算n可能的最小值和最大值。

Input

第一行兩個整數l,k,表示刷題機的日誌一共有l行,一共了切了k題。 第二行l個整數,x1…xl。xi>=0表示寫了xi行代碼。xi<0表示刪除了這道題的-xi行代碼。 1<=l,k<=100000,|xi|<=10^9

Output

輸出兩個數a,b。分別代表n可能的最小值和最大值。如果不存在這樣的n則輸出-1。

Sample Input

4 2
2
5
-3
9

Sample Output

3 7
//樣例1:如果n=2那麽刷題機就會切掉3題。但如果n>7刷題機最多只能切1題。考慮n=4發生了什麽。
第一秒:刷題機寫了2行。
第二秒:刷題機又寫了5行,共有7行,提交,自信AC。
第三秒:刷題機刪掉了3行,共有0行。
第四秒:刷題機寫了9行,共有9行,提交,自信AC。
一共AC了兩題。

思路:

  二分答案,因為是固定長度的代碼。分兩次二分,一次二分上界,一次二分下界,check分成三種情況,等於ans、大於ans或小於ans,大於和小於的話兩種二分的狀態是一樣的,如果等於,一個趨近於更小,一個趨近於更大。

代碼如下

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define ll long long
ll n,tar;
int a[100001];
int check(ll x) {
    ll now=0,ret=0;
    for(int i=1;i<=n;i++) {
        if(now>-a[i])
            now+=a[i];
        else {
            now=0;
            continue;
        }
        if(now>=x)ret++,now=0;
    }
    if(ret>tar)return 1;
    if(ret<tar)return -1;
    else return 0;
}
int main() {
    //puts("-1");
    //return 0;
    scanf("%lld%lld",&n,&tar);
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
    }
    int t=100;
    bool flag=0;
    ll l=1,r=1ll<<60;
    while(t--) {
        ll mid=(l+r)>>1;
        int k=check(mid);
        if(k==0) {
            flag =1;
            r=mid-1;
        }
        else if(k==-1) {
            r=mid-1;
        }
        else {
            l=mid+1;
        }
    }
    if(!flag)
    {
        puts("-1");
        return 0;
    }
    l=1,r=1ll<<60;
    while(l<r) {
        ll mid=(l+r)>>1;
        int k=check(mid);
        if(k==0) {
            r=mid-1;
        }
        else if(k==-1) {
            r=mid-1;
        }
        else {
            l=mid+1;
        }
    }
    while(check(l))l++;
    if(l==0)l++;
    printf("%lld ",l);
    l=1,r=1ll<<60;
    while(l<r) {
        ll mid=(l+r)>>1;
        int k=check(mid);
        if(k==0) {
            l=mid+1;
        }
        else if(k==-1) {
            r=mid-1;
        }
        else {
            l=mid+1;
        }
    }
    while(check(l))l--;
    printf("%lld",l);
}

BZOJ 4590: [Shoi2015]自動刷題機