zoukankan      html  css  js  c++  java
  • 【基础】dp系列1

    序列双段最大子段和问题

    (也许很水但蒟蒻刚刚学dp就来记录一下)

    题目链接

    题意就是求序列中的任意两段的最大子段和最大。

    我们先预处理出来前缀和,方便求最大子段和。

    对于每一个i都求一遍1到i的最大子段和,即:

    pre[1]=a[1];
        minn=min(0,a[1]);
        for(int i=2;i<n;i++){
            minn=min(minn,a[i]);
            pre[i]=max(pre[i-1],a[i]-minn);
        }

    其中,a数组是前缀和,直接处理的。

    那么,我们再对n到1的每一个i求一遍最大子段和,即:

    post[n]=a[n]-a[n-1];
        maxn=a[n];
        for(int i=n-1;i>1;i--){
            maxn=max(maxn,a[i]);
            post[i]=max(post[i+1],maxn-a[i-1]);
        }

    那么,接下来我们要做些什么?

    枚举每一个i,从1到n-1,求出前i个数的最大子段和和i第i+1个数到n的最大子段和之和的最大值。

    即:

    ans=-inf;
        for(int i=1;i<n;i++)ans=max(ans,pre[i]+post[i+1]);
        printf("%d
    ",ans);

    完整代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define inf 2147483647
    using namespace std;
    int t,n,a[50001];
    int maxn,minn,pre[50001];
    int post[50001],ans;
    inline void solve(){
        pre[1]=a[1];
        minn=min(0,a[1]);
        for(int i=2;i<n;i++){
            minn=min(minn,a[i]);
            pre[i]=max(pre[i-1],a[i]-minn);
        }
        post[n]=a[n]-a[n-1];
        maxn=a[n];
        for(int i=n-1;i>1;i--){
            maxn=max(maxn,a[i]);
            post[i]=max(post[i+1],maxn-a[i-1]);
        }ans=-inf;
        for(int i=1;i<n;i++)ans=max(ans,pre[i]+post[i+1]);
        printf("%d
    ",ans);
        memset(pre,0,sizeof(pre));
        memset(post,0,sizeof(post));
    }
    int main(){
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            for(int i=1;i<=n;++i)scanf("%d",&a[i]),a[i]+=a[i-1];
            solve();
        }
        return 0;
    }
  • 相关阅读:
    mybatis plus 执行sql
    springboot 打印 mybatisplus 的sql
    easyexcel 简单使用
    springboot ehcache
    easyexcel 时间转换
    springboot stopwatch
    c# 开机自动启动
    sqlHelper
    DirectX录音
    c# 发邮件
  • 原文地址:https://www.cnblogs.com/h-lka/p/11136427.html
Copyright © 2011-2022 走看看