1. 程式人生 > >【BZOJ4590】[Shoi2015]自動刷題機 二分

【BZOJ4590】[Shoi2015]自動刷題機 二分

printf 代碼 個數 tdi using 結果 所有 sam lld

【BZOJ4590】[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了兩題。

題解:顯然滿足單調性,直接二分。

判-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]自動刷題機 二分