题目描述
小红拿到了一个数组,她希望进行最多一次操作: 将一个元素修改为XXX。小红想知道,最终的连续子数组最大和最大是多少?
输入描述
第一行输入一个正整数ttt,代表询问次数。
对于每次询问,输入两行:
第一行输入两个正整数nnn和xxx。代表数组的大小,以及小红可以修改成的元素。
第二行输入nnn个正整数aia_iai,代表小红拿到的数组。
1≤t≤1000001 \leq t \leq 1000001≤t≤100000
1≤n≤2000001 \leq n \leq 2000001≤n≤200000
−109≤x,a1≤109-10^9 \leq x,a_1 \leq 10^9−109≤x,a1≤109
每组所有询问的nnn的和不超过200000200000200000。
输出描述
输出t行,每行输出一个整数,代表连续子数组的最大和。
样例
输入
3
5 10
5 -1 -5 -3 2
2 -3
-5 -2
6 10
4 -2 -11 -1 4 -1
输出
15
-2
15
提示
第一组询问,修改第二个数。
第二组询问,不进行任何修改。
第三组询问,修改第三个数。
思路
step1:不带修改
如果不带修改,那么就是朴素的最大子段和。经典dp
step2:带修改
某个位置改成xxx之后,我们要考虑的是必须包含这个位置的最大子段和。那么也就是左边一段(可以为空)拼上xxx再拼上右边一段(可以为空),如下图所示
容易发现,AAA 必须是以ai−1a_{i-1}ai−1 结尾的最大子段和。BBB必须是以ai+1a_{i+1}ai+1 为开头的最大子段和。
证明:反证法
令AAA是以aia_iai为结尾的最大子段和。
假设存在一个更大的A′>AA' > AA′>A 。由于A′A'A′也是以aia_iai 为结尾的子段。可以推出AAA 并不是最大子段和,和假设冲突。
所以AAA 一定要是最大子段和
所以做法就是:正着求一遍最大子段和dpdpdp,反着求一遍最大子段和fff。
答案为:不修改的最大子段和 与 枚举每个位置尝试修改的最大子段和 , 两者的最大值
对于前者,答案就是max(dp)max(dp)max(dp)
对于后者的第iii 个位置 , max(dp(i−1),0)+x+max(f(i+1,0))max(dp(i-1) , 0)+x+max(f(i+1 , 0))max(dp(i−1),0)+x+max(f(i+1,0))
注意,对000 取最大值是代表左右两个段可以为空
代码
def read_input():
# Read the number of test cases
t = int(input())
# Iterate over each test case
test_cases = []
for i in range(t):
# Read the input for the current test case
n, x = map(int, input().split())
a = list(map(int, input().split()))
test_cases.append((n, x, a))
return test_cases
def calculate_dp(n, a):
# Initialize the dp array
dp = [0] * (n + 2)
# Calculate the dp array
for j in range(1, n + 1):
dp[j] = max(dp[j - 1], 0) + a[j - 1]
return dp
def calculate_f(n, a):
# Initialize the f array
f = [0] * (n + 2)
# Calculate the f array
for j in range(n, 0, -1):
f[j] = max(f[j + 1], 0) + a[j - 1]
return f
def calculate_ans(n, x, a, dp, f):
# Initialize the answer
ans = 0
# Calculate the answer
# Case 1: Do not modify any value
ans = max(dp[1:n + 1])
# Case 2: Modify each value and check the maximum subarray sum
for j in range(1, n + 1):
ans = max(ans, x + max(dp[j - 1], 0) + max(f[j + 1], 0))
return ans
def solve_test_cases(test_cases):
# Iterate over each test case
for n, x, a in test_cases:
# Calculate the dp array
dp = calculate_dp(n, a)
# Calculate the f array
f = calculate_f(n, a)
# Calculate the answer
ans = calculate_ans(n, x, a, dp, f)
# Print the answer for the current test case
print(ans)
test_cases = read_input()
solve_test_cases(test_cases)
文章描述了一种算法问题,要求在给定数组中,通过最多一次将某个元素修改为特定值X,找到连续子数组的最大和。解决方案包括使用动态规划分别从左右两端计算最大子数组和,并针对每个位置的修改进行计算,取最大值作为最终答案。

被折叠的 条评论
为什么被折叠?



