ACderem之循环数列的最大连续子序列和

本文探讨了如何帮助角色娜娜最大化获取糖果的数量,面对黑洞的挑战,通过策略分析和算法实现,确保娜娜能够安全且高效地带走尽可能多的糖果。文中详细解释了解决方案,包括数据输入格式、输出结果预期,以及关键步骤的代码实现,旨在为类似问题提供解决思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem Description

娜娜好不容易才在你的帮助下"跳"过了这个湖,果然车到山前必有路,大战之后必有回复,大难不死,必有后福!现在在娜娜面前的就是好多好多的糖果还有一些黑不溜秋的东西!不过娜娜眼中只有吃不完的糖果!娜娜高兴地快要蹦起来了!

 

这时有一位挥着翅膀的女孩(天使?鸟人?)飞过来,跟娜娜说,这些糖果是给你的~(娜娜已经两眼放光)~你可以带走~(娜娜已经流下了口水)~但是~(神马?还有但是?)~这位神仙姐姐挥一挥翅膀~飘过了一片云彩,糖果和那些黑不溜秋的东西顿时飞了起来,落到地上成了摆成一个奇怪的图形。

 

神仙姐姐很满意,转过来对娜娜说:“这些糖果和黑洞(神马?黑洞?)分成n堆,每堆要么都是糖果,要么是黑洞,围成一个圈(即第1堆的旁边是第n堆和第2堆),你可以选择连续若干堆,然后带走,不过这些黑洞嘛,会馋嘴的小孩吸进去,你必须拿糖果去中和掉。”

 

娜娜喜欢糖果,但不喜欢动脑子~于是就把这个问题交给你,怎样才能让娜娜带走最多的糖果呢?

Input

多组数据,首先是一个正整数t(t<=20)表示数据组数

对于每组数据,包括两行,第一行是一个正整数n(3<=n<=100000)表示堆数

第二行是n个整数x[i](1<=|x[i]|<=1000),如果是个正整数,则说明这是一堆数量为x[i]的糖果,如果是个负整数,则说明这是一个需要用abs(x[i])颗糖果去中和的黑洞。

Output
对于每组数据,输出一个整数,表示娜娜最多能带走的糖果数。
Sample Input
3
5
1 2 3 4 5
5
1 -2 3 -4 5
5
-1 -2 -3 -4 -5
Sample Output
15
7
0
Hint

对于样例1,娜娜可以把所有的糖果都拿走,所以输出15(=1+2+3+4+5)

对于样例2,娜娜可以拿走第1,2,3,5堆的糖果,别忘了这是摆成一个圈,所以输出7(=1+(-2)+3+5)

对于样例3,等待娜娜的是5个黑洞,可怜的娜娜,一个糖果都拿不掉,所以输出0

由于输入数据较多,请谨慎使用cin/cout

这题当时我个人想的是扩充数组为2*n,但是后来发现怎么也不对,打完比赛队友给我指出来错误,原来我的思路从一开始就不是很对,

或者说我没办法用哪个思路敲出来正确的代码,队友告诉我,求非循环数列的最大值,同非循环数列总和减去非循环数列的最小值思路比较简单

,但是个人感觉不是很好理解,贴下代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<string>
#include<map>
#include<set>
#include<vector>
using namespace std;
const int N=1e5+10;
int a[N];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        int asum=0,bsum=0,amax=0,amin=0;
        for(int i=0;i<n;i++)
            asum+=a[i];
        for(int i=0;i<n;i++)
        {
            bsum+=a[i];
            if(bsum>amax)
                amax=bsum;
            if(bsum<0)
                bsum=0;
        }
        for(int i=0;i<n;i++)
        {
            bsum+=a[i];
            if(bsum<amin)
                amin=bsum;
            if(bsum>0)
                bsum=0;
        }
        if(asum-amin>amax)
            amax=asum-amin;
        cout<<amax<<endl;
    }
    return 0;
}

后来发现月神的代码思路比较严谨,比较容易理解,就模仿着写了一发:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<cctype>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#define LL long long
using namespace std;
const int N=1e5+10;
int a[N],fsum[N];
int main()
{
    int t ;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        int asum=0,tsum=0,amax=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            if(tsum<0)
                tsum=0;
            tsum+=a[i];
            asum+=a[i];
            fsum[i]=max(fsum[i-1],asum);
            amax=max(amax,tsum);
        }
        tsum=0;
        for(int i=n-1;i>=0;i--)
        {
            tsum+=a[i];
            amax=max(fsum[i-1]+tsum,amax);
        }
        cout<<amax<<endl;
    }
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值