最大子段和比较好求解,就是一个dp标记走就可以了,当dp<0,让dp等于当前位,dp大于0就加上当前位就好。
最小子段和就是把所有的元素去相反数,然后在此基础上求一个最大子段和就好。
主要想说的是最小正子段和的求法,是先算前i位的累加和dp[i],并记录标记为i。
然后对所有的dp[i]进行小到大的排序,然后对两个相连的dp[i],如果后者的标记大于前者的标记,那么它们的差值是候选答案,然后选取候选答案最小的那个。
PS:注意要在里面加一个标记为-1的,和为0的节点。
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
/***********************
51nod 1065最小正子段和
***********************/
struct Node{
__int64 val, flag;
};
Node node[50005];
__int64 N, num[50005];
bool comp(Node a, Node b)
{
if(a.val == b.val)
return a.flag > b.flag;
return a.val < b.val;
}
int min(int a, int b)
{
if(a < 0) return b;
return a < b ? a : b;
}
void solve()
{
for(int i = 0; i < N; i ++)
cin>>num[i];
//将每一项进行累加操作
node[0].flag = -1, node[0].val = 0;
for(int i = 1; i <= N; i ++){
node[i].flag = node[i - 1].flag + 1;
node[i].val = node[i - 1].val + num[i - 1];
}
//然后进行排序
sort(node, node + N + 1, comp);
int ans = -1;
//当排序后,相连两项,它的后面一项的标记大于前面一项的标记时,它是候选答案之一,进行<span style="white-space:pre"> </span>//比较即可,注意加上一项为0的
for(int i = 1; i <= N; i ++){
if(node[i].flag > node[i - 1].flag){
if(node[i].val - node[i - 1].val > 0)
ans = min(ans, node[i].val - node[i - 1].val);
}
}
cout<<ans<<endl;
}
int main()
{
while(cin>>N){
solve();
}
}