搜索
简帛阁>技术文章>hdu 5280 贪心 O(n)算法

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
总是少一个的原因就是假设修改的那一个元素并没有影响到当前答案
如果修改后的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]
 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 }

 

题意给你一个序列A[1N],你必须修改一个A[i]为P,使得修改后的序列A的连续最大和最大其中N<1000分析,N非常小,N^2暴力随便做,不细讲说一个O(N)的算法我们知道O(N)的求连续最大
信很多开发的同伴们在研究算法、排序的时候经常会碰到O(1),O(n),O(logn),O(nlogn)这些复杂度,看到这里就会有个疑惑,这个O(N)到底代表什么呢?首先o(1),o(n),o(log
Java中Set和List集合的contains()方法,检查数组链表中是否包含某元素检查数组链表中是否包含某元素,使用Set而不使用List的原因是效率问题,前者的setcontains()方法实现
义在一个规模为N的数组A[N]中,所谓主元素就是出现次数大于N/2的元素,例如334244244有一个主元素为4。充分利用主元素的出现次数大于N/2这个已知条件,因为主元素的出现次数大于N/2,所以
本随笔来源于《剑指offer》第二版面试官:请实现一个排序算法,要求时间效率为O(n)。应聘者:对什么数字进行排序,有多少个数字?面试官:我们相对公司的所有员工的年龄排序。我们公司一共有几万名员工。
importjavautilScanner;/***迪杰斯特拉算法:单源点到其他点的最短路径及距离*/publicclassPtest{//不能设置为IntegerMAX_VALUE,否则两个Inte
信很多开发的同伴们在研究算法、排序的时候经常会碰到O(1),O(n),O(logn),O(nlogn)这些复杂度,看到这里就会有个疑惑,这个O(N)到底代表什么呢?首先o(1),o(n),o(log
文实例讲述了C++实现查找中位数的O(N)算法和Kmin算法,分享给大家供大家参考。具体方法如下:利用快速排序的partition操作来完成O(N)时间内的中位数的查找算法如下:include<
算法基础~链表~求两个链表的交点(时间复杂度O(n)、空间复杂度O(1))1,接着上一篇的优化思路:https://wwwcnblogscom/shan333/p/15033376html2,还记得
在描述算法复杂度时,经常用到o(1),o(n),o(logn),o(nlogn)来表示对应算法的时间复杂度,这里进行归纳一下它们代表的含义:这是算法的时空复杂度的表示。不仅仅用于表示时间复杂度,也用