链接:https://ac.nowcoder.com/acm/contest/949/D
来源:牛客网
水果店里有 n个水果排成一列。店长要求顾客只能买一段连续的水果。
小阳对每个水果都有一个喜爱程度 ai,最终的满意度为他买到的水果的喜欢程度之和。
如果和为正(不管是正多少,只要大于 0即可),他就满意了。
小阳对每个水果都有一个喜爱程度 ai,最终的满意度为他买到的水果的喜欢程度之和。
如果和为正(不管是正多少,只要大于 0即可),他就满意了。
小阳想知道在他满意的条件下最多能买多少个水果。
你能帮帮他吗?输入描述:
第一行输入一个正整数 n,表示水果总数。
第二行输入 n 个整数 ai,表示小阳对每个水果的喜爱程度。
输出描述:
一行一个整数表示结果。(如果 1 个水果都买不了,请输出 0)
备注: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 }