hdu 5280 贪心 O(n)算法
题意给你一个序列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...n-1的最大L[i], 2...n的最大的R[i] 而不是全部跑一遍
都是少一个?
都是少一个?
因为必须修改A[1...n]中的某一个元素为P
比如说
n = 3 P = -100
A[1...3] = {10, 10, 10}
那么答案就是20,并非30
总是少一个的原因就是假设修改的那一个元素并没有影响到当前答案
比如说
n = 3 P = -100
A[1...3] = {10, 10, 10}
那么答案就是20,并非30
总是少一个的原因就是假设修改的那一个元素并没有影响到当前答案
如果修改后的A[i]=P并没有在最大的连续子段和中,那么一定在这连续子段和之外,设这个最大连续子段和的子段为A[l...r],一定保证l>1或者r<n,不然最大连续子段和的子段就变成A[1...n],与前面矛盾,那么我们就可以把A[1]变成P或者把A[n]变成P
若i=n,那么我们就只需要枚举L[1...n - 1]
若i=1,那么我们就只需要枚举R[2..n]
若i=n,那么我们就只需要枚举L[1...n - 1]
若i=1,那么我们就只需要枚举R[2..n]
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 }