小阳买水果

链接:https://ac.nowcoder.com/acm/contest/949/D
来源:牛客网

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

输入描述:

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

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

输出描述:

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

输入

复制
5
0 0 -7 -6 1

输出

复制
1

备注:

1≤n≤2×1e6,∣ai∣≤1e3


两种做法:
O(n)
就是前缀和排个序,
求一下前缀和,并且记录每个前缀和的位置,然后把 前缀和从小 到大排序,前缀和相同按照位置,从大到小排序。

区间和等于两个前缀和相减。排序之后前缀和小的在前大的 在后,只需从前 往后遍历一遍,记录最小位置即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e6+5;
struct node{
    ll a;
    int p;
}a[maxn];
bool cmp(node a,node b){
    if(a.a==b.a) return a.p>b.p;
    else return a.a<b.a;
}
int main(){
    a[0].a=0,a[0].p=0;
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i].a);
        a[i].a+=a[i-1].a;
        a[i].p=i;
    }
    sort(a,a+n+1,cmp);
    int p=a[0].p;
    int ans=0;
    for(int i=1;i<=n;i++){
        if(a[i].p>p){
            ans=max(ans,a[i].p-p);
        }else{
            p=a[i].p;
        }
    }
    printf("%d\n",ans);
    return 0;
}

 


首先一个数组a记录权值,然后数组sum保存a的前缀和,数组psum表示从后往前的sum 最大值(即max后缀,易知psum是 单调递减 的),然后枚举起点l(1-n),每次循环令r=n,pos,通过 二分 找到 最大的pos使得满足psum[mid]-sum[l-1]>0(满足题意),然后此时的长度就为pos-i+1,每次循环取max即可~


dalao原话:利用前缀和的后缀max的单调性,它是单调递减的,sum[i]表示前缀和,pmax[i]表示从i~n中最大的sum[j],i<=j<=n。然后枚举起点i,在[i,n]上二分终点,只要pmax[mid]>sum[i-1]就表示满足条件,继续增加l=mid+1,否则不满足条件令r=mid-1


#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+5;
const int mod=1e9+7;
typedef long long ll;
int n,ans;
int a[maxn],sum[maxn],psum[maxn];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",a+i);
        sum[i]=sum[i-1]+a[i];
    }
    psum[n]=sum[n];
    for(int i=n-1;i>=1;i--) psum[i]=max(psum[i+1],sum[i]);
    for(int i=1;i<=n;i++){
        int l=i,r=n,pos=0;
        while(l<=r){
            int mid=(l+r)>>1;
            if(psum[mid]>sum[i-1]){
                l=mid+1;
                pos=mid;
            }
            else r=mid-1;
        }
        ans=max(pos-i+1,ans);
    }
    cout<<ans<<endl;
}

 

 
posted @ 2021-01-22 13:52  lipu123  阅读(162)  评论(0)    收藏  举报