zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", ans);
    55     }
    56     return 0;
    57 }
  • 相关阅读:
    easyui dialog 中 panel-body 高度太小出现 滚动条 的原因
    VS2017 未找到编译器可执行文件 csc.exe
    苹果个人开发者账号开发证书申请
    react-native android 报错 error calling Appregistry.runApplication
    react-native android 权限问题
    安卓证书生成
    node.js定时任务 node-schedule
    node.js 发送邮件
    在移动端点击事件触发时,闪烁并且有灰色背景
    antd-mobile使用报错
  • 原文地址:https://www.cnblogs.com/addf/p/4640464.html
Copyright © 2011-2022 走看看