解题思路
此题目大体意思:每行一个整数x代表一秒钟输入x行代码,若为负数则代表删除了x行代码(0行删除代表一行代码也没有输入),切了k题代表AC了k道题。n代表要AC题目所需要的代码行数,求出所需n的最大值与最小值。
由题意得我们可以枚举答案,再一个个去check(),但暴力枚举必然会超时,所以我们可以二分答案来降低时间复杂度,因为需要求一个最大值和一个最小值,所以我们要二分两次求出答案。
check()函数我们用来判断当我们输入n后其切题的次数,再在二分循环判断n是大是小。尤其强调一下跳出循环查找的边界,因为最后结束left<right(且相邻),最终满足题意的答案一定是其中之一,那么我们可以在循环结束后分别进行判断check(left/right)==k来得到结果。这样不需要把判断放在循环内部减少不必要判断次数;其次在求最大值n的时候可以设置sum(xi)为右边界,求最小值n时候则可以设置最大值n来作为右边界,降低时间复杂度.
完整代码
l,k=map(int,input().split())
a=[]
for _ in range(l):
a.append(int(input()))
left=1
right=sum(abs(i) for i in a)
def check(x):#模拟
sumn=0
line=0
for i in range(l):
sumn+=a[i]
if sumn>=x:
line+=1
sumn=0
if sumn<0:sumn=0
return line
while left<=right:
mid=(left+right)//2
if check(mid)>=k:
left=mid+1
else:right=mid-1
maxn=-1
if check(right)==k:
maxn=right
elif check(left)==k:
maxn=left
if maxn==-1:
print(-1)
else:
left=1
right=maxn
while left<=right:
mid=(left+right)//2
if check(mid)<=k:
right=mid-1
else:
left=mid+1
if check(left)==k:
minn=left
elif check(right)==k:
minn=right
print(f"{minn} {maxn}")