Maximum sum(信息学奥赛一本通-T1305)

本文介绍了一种算法,用于解决给定整数序列中找到两个不重叠连续子段的最大和问题。通过预处理得到左右最大子段和,再遍历数组计算最大组合和,最终得出d(A)的值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目描述】

对于给定的整数序列A={a1,a2,...,an},找出两个不重合连续子段,使得两子段中所有数字的和最大。我们如下定义函数 d(A):

我们的目标就是求出d(A)。

【输入】

第一行是一个整数T(≤30),代表一共有多少组数据。

接下来是T组数据。

每组数据的第一行是一个整数,代表数据个数据n(2≤n≤50000) ,第二行是nn个整数a1,a2,...,an(|ai|≤10000)。

【输出】

输出一个整数,就是d(A)的值。

【输入样例】

1
10
1 -1 2 2 3 -3 4 -4 5 -5

【输出样例】

13

【源程序】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 50001
#define MOD 50001
#define E 1e-12
using namespace std;
int a[N];
int leftt[N],rightt[N];
int leftmax[N],rightmax[N];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];

        leftt[1]=a[1];
        leftmax[1]=a[1];
        rightt[n]=a[n];
        rightmax[n]=a[n];

        for(int i=2;i<=n;i++)
            leftt[i]=max(a[i],leftt[i-1]+a[i]);
        for(int i=n-1;i>=1;i--)
            rightt[i]=max(a[i],rightt[i+1]+a[i]);
        for(int i=2;i<=n;i++)
            leftmax[i]=max(leftmax[i-1],leftt[i]);
        for(int i=n-1;i>=1;i--)
            rightmax[i]=max(rightmax[i+1],rightt[i]);

        int ans=a[1];
        for(int i=2;i<=n;i++)
            ans=max(ans,leftmax[i-1]+rightmax[i]);

        cout<<ans<<endl;
    }
    return 0;
}

 

当前提供的引用内容并未涉及信息学奥赛一本 C++ 题目编号范围 3800 至 3900 的具体解答或相关内容。然而,可以过分析已有的引用材料以及常见的解题思路来推测可能的解决方法。 以下是针对此类问题的一些用解决方案框架: ### 解决方案概述 #### 条件判断与分支结构 对于许多编程题目,尤其是涉及到条件判断的问题,可以采用 `if` 或者嵌套 `if-else` 结构来进行逻辑控制[^3]。例如,在验证某个整数是否位于特定范围内时,可利用如下代码片段作为模板: ```cpp #include <iostream> using namespace std; int main() { int num; cin >> num; // 输入待检测的整数 if (num > lower_bound && num < upper_bound) { // 替换lower_bound和upper_bound为实际边界值 cout << "yes"; } return 0; } ``` #### 循环处理大量数据 当面对需要重复执行相同操作的任务时,循环语句显得尤为重要。比如累加一系列数字或者查找数组中的最大/最小值等问题都可以过 `for`, `while` 等循环机制完成。下面展示了一个简单的求和例子: ```cpp #include <iostream> using namespace std; int main(){ long sum = 0; for(int i=1;i<=n;i++)//假设n已经定义并初始化好 sum +=i ; cout<<sum<<endl; return 0; } ``` #### 数组与矩阵运算 部分复杂度较高的算法可能会用到二维甚至多维的数据存储形式——即数组或向量。像鞍点计算这样的经典问题就需要遍历整个二维表找到符合条件的位置[^1]。这里给出一个简化版本用于说明如何定位鞍点位置: ```cpp #include <bits/stdc++.h> using namespace std; void findSaddlePoint(int mat[][N], int n){ bool flag=false; /* Iterate through rows */ for (int i=0;i<n;i++){ int min_row=mat[i][0]; int col_ind=0; // Find minimum element of current row. for (int j=1;j<n;j++){ if(min_row>mat[i][j]){ min_row=mat[i][j]; col_ind=j; } } // Check whether this is also maximum in its column or not. int k; for( k=0 ;k<n;k++) if(mat[k][col_ind]>min_row){ break; } if(k==n){ printf("Value of Saddle Point %d\n",min_row); flag=true; } } if(!flag) printf("No Saddle Point"); } ``` 以上仅提供了几种常见类型的程序设计模式供参考,并未直接对应具体的第3800至3900号之间的每一道试题答案。由于这些高序号习题往往更加注重综合运用能力,建议查阅官方教材获取权威指导资料的同时积极尝试独立思考解决问题的方法路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值