程序设计:蒜厂年会(dp)(vj)

在蒜厂年会上有一个抽奖,在一个环形的桌子上,有 nn 个纸团,每个纸团上写一个数字,表示你可以获得多少蒜币。但是这个游戏比较坑,里面竟然有负数,表示你要支付多少蒜币。因为这些数字都是可见的,所以大家都是不会出现的赔的情况。

游戏规则:每人只能抓一次,只能抓取一段连续的纸团,所有纸团上的数字和就是你可以获得的蒜币。

蒜头君作为蒜厂的一员在想,我怎么可以获得最多的蒜币呢?最多能获取多少蒜币呢?

因为年会是发奖,那么一定有大于 00 的纸团。

输入格式

第一行输入一个整数 nn,表示有 nn 个纸团。

第二行输入输入 nn 个整数 a_iai​,表示每个纸团上面写的数字(这些纸团的输入顺序就是环形桌上纸团的摆放顺序)。

输出格式

输出一个整数,表示蒜头君最多能获取多少蒜币。

数据范围

对于 30\%30% 的数据:1 \le n \le 10^2,-10^3 \le a_i \le 10^31≤n≤102,−103≤ai​≤103。

对于 60\%60% 的数据:1 \le n \le 5 \times 10^3,-10^6 \le a_i \le 10^61≤n≤5×103,−106≤ai​≤106。

对于 100\%100% 的数据:1 \le n \le 10^5,-10^9 \le a_i \le 10^91≤n≤105,−109≤ai​≤109。

样例输入

3
1 -2 1

样例输出

2

 

思路:

此题难点在于围成了一个圈。

如果不是一个圈,那么就是简单的一个动归,求出最大的连续序列和。

其实围成一个圈也不难,除了上述情况,还要考虑一种情况,那就是从a[n]循环回a[0]的情况下最大序列和是多少,两种情况取最大即可。对于第二种情况,循环回去不好求,可以把它当作不是一个圈求出最小的连续序列和,然后用总和减去,得到的就是两边循环起来的最大的连续序列和。

爱吃代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
long long a[100010];
int main()
{
    int n,i,book=0;
    long long sum=0,maxx=0,minn=0,ans=0;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        scanf("%lld",&a[i]);
        ans+=a[i];
    }
    for(i=0;i<n;i++)
    {
        sum+=a[i];
        if(sum<=0)
            sum=0;
        else
            maxx=max(maxx,sum);
    }
    sum=0;
    for(i=0;i<n;i++)
    {
        sum+=a[i];
        if(sum>=0)
            sum=0;
        else
            minn=min(minn,sum);
    }
    ans=ans-minn;
    printf("%lld\n",max(ans,maxx));
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值