NBUT 1593 Max Sum 【环上最大子段和】

题目:链接

题意:求环上的最大子段和。

醉了因为long long WA成狗了,用__int64。。。


思路一:考虑以a[i]结尾的状态。状态来源有两个

1,区间[j, i]的和(1<=j<=i);2,区间[j, n] + [1, i]的和(i < j <= n)。

来源1——直接dp就好了。 来源2——维护区间[i+1, n]的最大后缀和即可。


思路二:记sum为总和,求出最大子段和sum1和最小子段和sum2,取max(sum1, sum-sum2)。


AC代码:(思路一)


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define CLR(a, b) memset(a, (b), sizeof(a))
using namespace std;
typedef __int64 LL;
const int MOD = 1e9+7;
const int MAXN = 1e5+10;
const LL INF = 1e11+10;
LL a[MAXN], Max[MAXN], dp;
void add(LL &x, LL y) {x += y; x %= MOD;}
int main()
{
    int t; scanf("%d", &t);
    int kcase = 1;
    while(t--)
    {
        int n; scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%I64d", &a[i]);
        LL sum = 0;
        for(int i = n; i >= 1; i--)
        {
            if(i == n)
                Max[i] = 0;
            else
                Max[i] = max(Max[i+1], sum);
            sum += a[i];
        }
        LL ans = -INF; sum = 0;
        for(int i = 1; i <= n; i++)
        {
            sum += a[i];
            if(i == 1) dp = a[i];
            else dp = max(a[i], dp + a[i]);
            ans = max(ans, dp);
            ans = max(ans, sum + Max[i]);
            //cout << ans << endl;
        }
        printf("Case %d: %I64d\n", kcase++, ans);
    }
    return 0;
}


你可能感兴趣的:(我就是DP)