• 最大子段和之环形问题


    环形最大子段和

    题目模型

    • 把模型一的线性变成环形。有一个修改,不允许区间为空。

    问题分析

    方法一:
    • 环形数组的连续最大子段和,有两种情况。

      1. 最大和的这个子段没有包含头尾。此时跟线型一样。
        • 定义dp[i]表示以a[i]结尾的最大子段和。
        • 转移方程:dp[i]=max(dp[i-1]+a[i],a[i])
      2. 最大和的这个子段包含了头尾。
        • 此时:最大子段和 = 整个序列和 - 最小子段和。
        • 此时最小子段和肯定是不包括头尾的,我们可以把原序列的每个元素乘以-1,然后求出最大子段和,即为原序列的不包括头、尾的最小子段和。
    • 然后比较两种情况的大小,输出大的那一个就行。

    • Code

      #include <bits/stdc++.h>
      const int maxn = 1e7+5,Inf=0x3f3f3f3f;
      typedef long long LL;
      LL a[maxn],b[maxn],dp[maxn];
      LL sum = 0,Max = 0,Min = 0;
      void Solve(){
          int n;scanf("%d",&n);
          srand(time(0));//随机种子
          for(int i=1;i<=n;++i){
              a[i]=rand()%10000-5000;//产生-5000~5000的随机数
              b[i]=-a[i];//原序列元素乘-1
              sum+=a[i];//序列之和
          }    
          for(int i=1;i<=n;++i){//对应情况1
              dp[i]=std::max(dp[i-1]+a[i],a[i]);
              Max=std::max(Max,dp[i]);
          }
          memset(dp,0,sizeof(dp));    
          for(int i=1;i<=n;++i){//对应情况2,求b的最大子段和,取反后为a的的最小子段和
              dp[i]=std::max(dp[i-1]+b[i],b[i]);
              Min=std::max(Min,dp[i]);
          }
          LL ans=std::max(Max,sum+Min);//sum+Min相当于序列和减去最小区间和
          printf("%lld
      ",ans);
      } 
      int main(){
          Solve();
          return 0;
      }
      
    方法二:
    • 可以用单调队列,具体做法见下一个模型。
  • 相关阅读:
    剖析下聊天室
    PHP与Nginx之间的运行机制以及原理
    Nginx源码结构
    Nginx初始化过程总结
    Nginx架构解析
    KMP && KMP求字符串循环节
    IOS开发之 ---- 苹果系统代码汉字转拼音
    jQuery--表单的过滤
    jQuery--子元素过滤
    存储过程 psal emp.sal%type是什么意思
  • 原文地址:https://www.cnblogs.com/hbhszxyb/p/13130908.html
Copyright © 2020-2023  润新知