最长连续和大于0(小阳买水果)

题目描述 

水果店里有 n个水果排成一列。店长要求顾客只能买一段连续的水果。
小阳对每个水果都有一个喜爱程度 ai,最终的满意度为他买到的水果的喜欢程度之和。
如果和为正(不管是正多少,只要大于 0 即可),他就满意了。

小阳想知道在他满意的条件下最多能买多少个水果。

你能帮帮他吗?

输入描述:

第一行输入一个正整数 n,表示水果总数。

第二行输入 n 个整数 ai,表示小阳对每个水果的喜爱程度。

输出描述:

一行一个整数表示结果。(如果 1 个水果都买不了,请输出 0)

输入

复制

5
0 0 -7 -6 1

输出

复制

1

备注:

1≤n≤2×10^6,|ai|≤10^3

链接:https://ac.nowcoder.com/acm/contest/949/D

解题思路:题意是在一个给定的数组中,求最长的连续和大于0,比如2,-5,2,0,-1,最长连续和大于0的片段是:2,0,-1,所以结果ans=3。既然是连续片段的问题,解题方法肯定要偏向尺取、线性。

如果是尺取方法,就会很麻烦,面临的问题就是右边界向右移一个值,在保证该片段和大于0情况下,求当前最长片段,就要左边界就要左移和右移,并将片段和、长度记录在有边界数下,思路很简单,但是代码不好写。

线性方法就很简单,先用结构体记录前缀和和当前位置,然后把前缀和从小到大sort,如果前缀和num相同按下标从大到小排序(这点很重要!),sort之前在结构体中再加一个空值下表=0,前缀和=0,将n+1个数组排序后,数组中的前缀和num必然是越来越大,所以数组后面num减数组前面num一定大于等于0,同时还要保证数组后面的下标pos大于前面的下标pos,因为只有在pos大于情况下,后面前缀和num才包括前面前缀和。在前后关系中,要想得到最长片段,必然前面pos越小,后面pos越大,所以最长max_ans=后面pos-前面pos

-4,5,1,-2,1,-3,1
前缀和num -4 -2 -1 0 0 1 1 2
下表pos 1 6 7 4 0 5 2 3

问题1:相同前缀和num下,下标pos从大到小排序?

比如num=0,pos排序为4和0,因为后num-前num=0,与题意不符合,这时候刚pos 0<pos 4,所以在计算ans时,不会算入。如果顺序是0和4,ans就会等于4-0=4。但是在上述数据中,并没有明显体现出来。

问题2:数组中加入空值num=0,pos=0,进行sort ?

想想如果不加时,pos最大为n,最小为1,max_ans=n-1,但是最长是ans=n,此时pos最大n,最小为0,才可以算出n=n-0。num=0和pos=0也算是分界点,num>0的部分 ,前缀片段都是从头开始计算,当前maxpos=pos-0,都可以进行正确计算。

#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
    int num,pos;  // 记录前缀和num,下标为pos
}a[2000010];      // a[pos]=num;
bool cmp(node x,node y)
{
    if(x.num==y.num)
    return x.pos>y.pos;
    return x.num<y.num;
}
void solve()
{
	int n;
    scanf("%d",&n);
    int x;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        a[i].num=a[i-1].num+x; //记录前缀和
        a[i].pos=i;            //当前下标pos
    }
    a[0].pos=0;
    a[0].num=0;			//加入一个num=0标志位 
    sort(a,a+n+1,cmp);      //(n+1)个前缀和从小到大排序
    int minpos=n,ans=0;
    for(int i=0;i<=n;i++)
    {
        minpos=min(minpos,a[i].pos);  //0到i个前缀和中,最小的下标
        if(minpos<a[i].pos)          
        ans=max(ans,a[i].pos-minpos); 
        //a[i].num-a[minpos].num>0 所以最长长度=当前前缀下标-最小的下标 
    }
    printf("%d\n",ans);
} 
int main()
{
    solve(); 
    return 0;
}
发布了39 篇原创文章 · 获赞 27 · 访问量 4145

猜你喜欢

转载自blog.csdn.net/qq_43381887/article/details/95864242