牛客-小阳买水果

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

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

输入描述:

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

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

输出描述:

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

输入

复制
5
0 0 -7 -6 1

输出

复制
1

备注:1≤n≤2×10^6,∣ai∣≤10^3

   分析: 用前缀和, 要求sum[b]-sum[a]>0,  且b与a距离越大越好, 最开始的想法是单调栈, 保留一个递减序列, 因为若sum[i]<sum[i+1}, 只有保留
sum[i]的需要, 然后二分就好啦。

  我看得别人的做法, 觉得很好很简洁(虽然复杂度相同); 从整体分析问题, 对sum前缀和排序, 相同的前缀,其下标大的在前面;
  然后便利这个有序sum序列, 这样就保证了后面的sum大于前面的sum, 为了寻找最大的间距, 我们维护一个最小下标就好了
  因为sum相同的时候, 下标大的在前面, 就排除掉了连续序列和为0的情况!

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=2e6+7;
 4 struct node {
 5     int val;
 6     int id;
 7     bool operator<(const node& x) const {
 8         if(val==x.val) return id>x.id;
 9         else           return val<x.val;
10     }
11 };
12 node t[N];
13 int n;
14 int main()
15 {
16     scanf("%d",&n);
17     for (int i=1;i<=n;i++) {
18         scanf("%d",&t[i].val);
19         t[i].val+=t[i-1].val;
20         t[i].id=i;
21     }
22     sort(t,t+1+n);
23     int min_id=n+7,ans=0;
24     for (int i=0;i<=n;i++) {
25         ans=max(ans, t[i].id-min_id);
26         min_id=min(t[i].id, min_id);
27     }
28     printf("%d
",ans);
29     return 0;
30 }
 
原文地址:https://www.cnblogs.com/xidian-mao/p/11398248.html