n = int(input()) nums = list(map(int, input().split())) # 计算前缀和和所有子数组的和 pre_sum = [0] all_sums = [] for i, x inenumerate(nums): s = 0 for j inrange(i, -1, -1): s += nums[j] all_sums.append(s) pre_sum.append(s) # 去重 all_sums = sorted(list(set(all_sums)))
defcheck(L: int, R: int) -> bool: q = deque([0]) # 划分点 for r inrange(n): # 单个值都超了最大值,直接 return if nums[r] > R: returnFalse while q: # 计算 [队头, r] 的子数组和 s = pre_sum[r + 1] - pre_sum[q[0]] if s < L: # 不到最小值,继续加入元素 break elif L <= s <= R: if r == n - 1and q[0] == 0: # 排除只有一个区间的情况,保证至少划分出两个区间 q.popleft() continue # [队头, r] 可以作为一个划分区间 # 之后要考虑的是以 r+1 作为左端点的区间,所以将 r+1 入队 q.append(r + 1) break else: # 比最大值都大了,缩小区间的范围(出队)再看看 q.popleft() # 如果队列不为空,变切最后一段也满足大于等于 L # 为什么再判断最后一段? # 因为上面的 if 里面如果最后一段比 最小值L 小就直接 break 了,但这是不符合条件的 return q and L <= pre_sum[-1] - pre_sum[q[0]] # <= R
left, right = 0, 0 ans = 0x3f3f3f3f while right < len(all_sums): while left <= right and check(all_sums[left], all_sums[right]): # 找到可以满足条件的划分,更新答案 ans = min(ans, all_sums[right] - all_sums[left]) left += 1 right += 1