【BZOJ4590】[Shoi2015]自動刷題機 二分
阿新 • • 發佈:2017-10-15
printf 代碼 個數 tdi using 結果 所有 sam lld
第一行兩個整數l,k,表示刷題機的日誌一共有l行,一共了切了k題。
第二行l個整數,x1…xl。xi>=0表示寫了xi行代碼。xi<0表示刪除了這道題的-xi行代碼。
1<=l,k<=100000,|xi|<=10^9
2
5
-3
9
//樣例1:如果n=2那麽刷題機就會切掉3題。但如果n>7刷題機最多只能切1題。考慮n=4發生了什麽。
第一秒:刷題機寫了2行。
第二秒:刷題機又寫了5行,共有7行,提交,自信AC。
第三秒:刷題機刪掉了3行,共有0行。
第四秒:刷題機寫了9行,共有9行,提交,自信AC。
一共AC了兩題。
【BZOJ4590】[Shoi2015]自動刷題機
Description
曾經發明了信號增幅儀的發明家SHTSC又公開了他的新發明:自動刷題機--一種可以自動AC題目的神秘裝置。自動刷題機刷題的方式非常簡單:首先會瞬間得出題目的正確做法,然後開始寫程序,每秒,自動刷題機的代碼生成模塊會有兩種可能的結果: A.寫了x行代碼。 B.心情不好,刪掉了之前寫的y行代碼。(如果y大於當前代碼長度則相當於全部刪除。) 對於每個OJ所有題目,存在某個固定的長度n>0。一旦自動刷題機在某秒結束時積累了大於等於n行的代碼,它就會自動提交並AC此題,然後新建一個文件開始寫下一題。SHTSC在某個OJ上跑了一天的自動刷題機,得到了很多條關於寫代碼的日誌信息。他突然發現自己沒有記錄這個OJ的n究竟是多少。所幸他通過自己在OJ上的Rank知道了機一共切了k道題。希望你計算n可能的最小值和最大值。Input
Output
輸出兩個數a,b。分別代表n可能的最小值和最大值。如果不存在這樣的n則輸出-1。Sample Input
4 22
5
-3
9
Sample Output
3 7//樣例1:如果n=2那麽刷題機就會切掉3題。但如果n>7刷題機最多只能切1題。考慮n=4發生了什麽。
第一秒:刷題機寫了2行。
第三秒:刷題機刪掉了3行,共有0行。
第四秒:刷題機寫了9行,共有9行,提交,自信AC。
一共AC了兩題。
題解:顯然滿足單調性,直接二分。
判-1的時候要註意,最後最好是再check一下判斷切題數是否正好等於K。並且二分的上界最好設的足夠大。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long ll; ll n,m; ll a1,a2; ll v[100010]; ll check(ll x) { ll i,ret=0; ll sum=0; for(i=1;i<=n;i++) { sum=max(0ll,sum+v[i]); if(sum>=x) ret++,sum=0; } return ret; } inline ll rd() { ll ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘) f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar(); return ret*f; } int main() { n=rd(),m=rd(); ll i; ll sum=0; for(i=1;i<=n;i++) v[i]=rd(),sum+=(v[i]>0)?v[i]:-v[i]; ll l=1,r=1ll<<60,mid; while(l<r) { mid=(l+r)>>1; if(check(mid)<=m) r=mid; else l=mid+1; } a1=r; l=2,r=1ll<<60; while(l<r) { mid=(l+r)>>1; if(check(mid)>=m) l=mid+1; else r=mid; } a2=l-1; if(check(a1)!=m||check(a2)!=m) printf("-1"); else printf("%lld %lld",a1,a2); return 0; }
【BZOJ4590】[Shoi2015]自動刷題機 二分