1007 Maximum Subsequence Sum

本题传送门

解题思路

这道题绝对不是模拟,贪心,很显然它们压根做不了。

由于其中有负数也有正数,要求最大子序列和,有一点点贪心思想,我们肯定是想要正数加在一起,这样我们可以标记所有正数的位置,然后算前缀和(凡是要求区间和的第一个要想到),我们对所有的标记两两搭配并计算区间和,暴力枚举,取最大的和,如果相等,按题目要求取左端点最小值,再相等,再取右端点最小值。

然后我们发现一个细节 0不影响区间和,如果左端点正数左边有0,i可以取到更小,所以我们上面标记的逻辑要改进一下,凡是大于等于0的时候都要做标记。

时间复杂度 \(O(N^2)\) , 显然在题目\(10^4\)的数据下会TLE,但是事实是,PAT直接过了,最高20ms,显然OJ的测试点极其友好。

但是说良心话,这道题本身的思维就很够了,如果还有大数据,这道题完全可以作为div2的题了。

ac✅️代码

#include<vector>
#include<iostream>
using namespace std;

int a[100010];
int sum[100010];
vector<int> mark;
int main()
{
    
    int n; cin>>n;
    for(int i = 1 ; i <= n ; i++)
    {
        cin>>a[i];
        sum[i] = sum[i-1] + a[i];
        
        if(a[i] >= 0) mark.push_back(i);
    }
    
    // 全是负数
    if(mark.size() == 0)
    {
        cout<<"0 "<<a[1] <<" "<<a[n]<<endl;
        return 0;
    }
    
    
    int l = 100001,r = -1,max_val = 0 ;
    
    for(int i = 0 ; i < mark.size() ; i ++)
    {
        for(int j = i ; j < mark.size(); j ++)
        {
            int cur = sum[mark[j]] - sum[mark[i] - 1];
            if(cur > max_val)
            {
                max_val = cur;
                l = mark[i] ;
                r = mark[j] ;
                
            }
                else if(cur == max_val)
            {
                if(mark[i] < l) l = mark[i];
                else if(mark[j] < r) r = mark[j];
            }
            
        }
    }
    
    cout<<max_val<<" "<<a[l]<<" "<<a[r]<<endl;
    return 0;
    
}
posted @ 2026-03-29 21:25  shuiwangrenjia  阅读(10)  评论(0)    收藏  举报