题目描述
曾经发明了信号增幅仪的发明家 SHTSC 又公开了他的新发明:自动刷题机——一种可以自动 AC 题目的神秘装置。
自动刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序。每秒,自动刷题机的代码生成模块会有两种可能的结果:
1.写了xx行代码
2.心情不好,删掉了之前写的yy行代码。(如果yy大于当前代码长度则相当于全部删除。)
对于一个 OJ,存在某个固定的长度n>0n>0,一旦自动刷题机在某秒结束时积累了大于等于nn行的代码,它就会自动提交并 AC 此题,然后新建一个文件(即弃置之前的所有代码)并开始写下一题。SHTSC 在某个 OJ 上跑了一天的自动刷题机,得到了很多条关于写代码的日志信息。他突然发现自己没有记录这个 OJ 的nn究竟是多少。所幸他通过自己在 OJ 上的 Rank 知道了自动刷题机一共切了kk道题,希望你计算nn可能的最小值和最大值。
输入格式
第一行两个整数ll,kk,表示刷题机的日志一共有ll行,一共了切了kk题。
第二行ll个整数x_1,...,x_lx1,...,xl。x_i≥0xi≥0表示写了x_ixi行代码,x_i<0xi<0代表删除了这道题的-x_i−xi行代码。
输出格式
输出两个数aa,bb,分别代表nn可能的最小值和最大值。如果不存在这样的nn则输出-1−1。
输入输出样例
输入 #1复制
4 2 2 5 -3 9
输出 #1复制
3 7
说明/提示
对于20%的数据,n≤10
对于40%的数据,n≤100
对于 60%的数据,n≤2000
对于 100%,n≤100000,-10^9≤x_i≤10^9−109≤xi≤109
思路
二分答案。不写二分答案其实就是模拟,当然会TLE。
#include <stdio.h>
#include <iostream>
#define ll long long int
#define inf 2e18+7
using namespace std;
ll l,k,minx,maxn,s,a[200001];
inline ll check(ll x)
{
register ll i,sum(0),line(0);
for(i=1;i<=l;i++)
{
sum+=a[i];//累加代码行数
if(sum>=x)//如果累加行数超过了mid
{
line++;//AC+1
sum=0;
}
sum=max(sum,(ll)0);//sum<0要为-
}
return line;
}
inline ll binary_max(ll l,ll r)
{
ll mid,ans(-1);
while(l<=r)
{
mid=(l+r)>>1;
if(check(mid)>k)
{
l=mid+1;
}
else
{
r=mid-1;
}
if(check(mid)==k)//句神烦的二分边界,这样写就A了
{
ans=mid;
}
}
return ans;
}
inline ll binary_min(ll l,ll r)
{
ll mid,ans(-1);
while(l<=r)
{
mid=(l+r)>>1;
if(check(mid)>=k)
{
l=mid+1;
if(check(mid)==k)
{
ans=mid;
}
}
else
{
r=mid-1;
}
}
return ans;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
register ll i,j;
cin>>l>>k;
for(i=1;i<=l;i++)
{
cin>>a[i];
}
maxn=binary_max(1,inf);
minx=binary_min(1,inf);
if(minx!=-1)
{
cout<<maxn<<' '<<minx<<endl;
}
else
{
cout<<-1<<endl;
}
return 0;
}