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;
}

浙公网安备 33010602011771号