题意给你一个序列A[1...N],你必须修改一个A[i]为P,使得修改后的序列A的连续最大和最大
其中N<=1000
分析,N非常小,N^2暴力随便做,不细讲
说一个O(N)的算法
我们知道O(N)的求连续最大和的算法
那么定义L[i], R[i]分别为L[i]以i为结尾的最大连续和,R[i]一i为开头的连续最大和
由于必须要修改一个A[i]为P,这个修改后的A[i]可能不包含在连续最大和中,也可能包含在连续最大和中
如果包含,那么就等价于:max(L[i - 1], 0) + max(R[i + 1], 0) + P
如果不包含,那么就计算1...n-1的最大L[i], 2...n的最大的R[i]
1 #include <set> 2 #include <map> 3 #include <queue> 4 #include <deque> 5 #include <cmath> 6 #include <vector> 7 #include <string> 8 #include <cstdio> 9 #include <cstdlib> 10 #include <cstring> 11 #include <cassert> 12 #include <iostream> 13 #include <algorithm> 14 15 #define dprint(expr) fprintf(stderr, #expr " = %d\n", expr) 16 17 using namespace std; 18 19 typedef long long LL; 20 typedef pair <int, int> PII; 21 22 const int N = 1e5 + 7; 23 const int INF = 0x3f3f3f3f; 24 const int MOD = 1e9 + 7; 25 const double EPS = 1e-6; 26 const double PI = acos(-1.0); 27 28 int a[N]; 29 LL l[N], r[N]; 30 31 int main(void){ 32 int T; 33 scanf("%d", &T); 34 while (T--) { 35 int n, p; 36 scanf("%d%d", &n, &p); 37 for (int i = 1; i <= n; ++i) 38 scanf("%d", &a[i]); 39 l[0] = r[0] = l[n + 1] = r[n + 1] = 0; 40 for (int i = 1; i <= n; ++i) 41 l[i] = max(l[i - 1] + a[i], (LL)a[i]); 42 for (int i = n; i; --i) 43 r[i] = max(r[i + 1] + a[i], (LL)a[i]); 44 LL ans = -INF; 45 for (int i = 1; i <= n; ++i) { 46 ans = max(ans, max(l[i - 1], 0LL) + max(r[i + 1], 0LL) + p); 47 } 48 for (int i = 1; i < n; ++i) { 49 ans = max(ans, l[i]); 50 } 51 for (int i = n; i > 1; --i) { 52 ans = max(ans, r[i]); 53 } 54 printf("%I64d\n", ans); 55 } 56 return 0; 57 }
时间: 2024-11-08 14:34:09