日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

小阳买水果(前缀和,单调栈,思维)

發(fā)布時間:2024/9/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小阳买水果(前缀和,单调栈,思维) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

鏈接:https://ac.nowcoder.com/acm/contest/949/D
來源:牛客網(wǎng)

水果店里有 nnn個水果排成一列。店長要求顧客只能買一段連續(xù)的水果。
小陽對每個水果都有一個喜愛程度 aia_iai?,最終的滿意度為他買到的水果的喜歡程度之和。
如果和為正(不管是正多少,只要大于 0即可),他就滿意了。
小陽想知道在他滿意的條件下最多能買多少個水果。
你能幫幫他嗎?

輸入描述:

第一行輸入一個正整數(shù) nnn,表示水果總數(shù)。

第二行輸入 nnn個整數(shù)aia_iai?,表示小陽對每個水果的喜愛程度。

輸出描述:

一行一個整數(shù)表示結果。(如果 1 個水果都買不了,請輸出 0)

示例1

輸入

5 0 0 -7 -6 1

輸出

1

備注:
1≤n≤2×1e61≤n≤2×1e 61n2×1e6,∣ai∣≤1e3∣a_ i ∣≤1e 3ai?1e3

代碼:

way1:

#include <bits/stdc++.h> using namespace std; const int MAXN = 2e6+5; #define INF 0x3f3f3f3f int sum[MAXN]; int s[MAXN]; int main() {int n;scanf("%d",&n);int x;sum[0] = 0;for(int i = 1; i <= n; i ++){scanf("%d",&x);sum[i] = sum[i-1] + x;}//way1:,sum數(shù)組存前綴和,s數(shù)組存i到最后的后綴最大和memset(s,-INF,sizeof(s));for(int i = n; i > 0; i--){s[i] = max(sum[i],s[i+1]);}int ans = 0;for(int i = 0,j = 1; i < n; i++,j++){if(sum[i]>=s[j]) //move at the same time,because ans that in the middle less than recent anscontinue;else{while(s[j]>sum[i]&&j<=n) j++;j--; // the last greater than sum[i]}ans = max(ans,j-i);}printf("%d\n",ans);return 0; }

way2:

#include <bits/stdc++.h> using namespace std; const int MAXN = 2e6+5; #define INF 0x3f3f3f3f int sum[MAXN]; int s[MAXN]; int main() {int n;scanf("%d",&n);int x;sum[0] = 0;for(int i = 1; i <= n; i ++){scanf("%d",&x);sum[i] = sum[i-1] + x;}//way2:s數(shù)組存前面到到i的前綴最小和s[0] = INF;for(int i = 1; i <= n; i++){s[i] = min(s[i-1],sum[i]);}int ans = 0;for(int i = 1; i <= n; i++){if(sum[i] > 0){ans = max(ans,i);}else if(s[i-1] >= sum[i]) continue;else{//the first less than sum[i] in range(1,i-1);int l = 1,r = i-1;int pos;while(l <= r){int mid = (l+r)>>1;if(s[mid] < sum[i]){pos = mid;r = mid - 1;}else{l = mid + 1;}}ans = max(ans,i-pos);}}printf("%d\n",ans);return 0; }

way3:

直接排序,按前綴和遞增排序,
前綴和相同所在位置大的(pos)排序
(ps: 前綴和相同時,pos小的在前面結果可能會更新,pos大的前面就能保證結果不被更新),
排序前要記錄原來的位置(pos)
為什么直接排序可以做呢?
基本思路是,排完序后,
后面的前綴和一定比前面的大,
只要前面有個 原來的index(pos)
比當前位置的 原來index(pos)小就可以更新答案

#include <bits/stdc++.h> using namespace std; const int MAXN = 2e6+5; struct Node {int sum;int pos;bool operator<(const Node &a)const{if(sum == a.sum)return pos > a.pos;return sum < a.sum;} }; Node a[MAXN]; int main() {int n;scanf("%d",&n);a[0].pos = 0;a[0].sum = 0;int x;for(int i = 1; i <= n; i++){scanf("%d",&x);a[i].pos = i;a[i].sum = a[i-1].sum + x;}sort(a,a+n+1);/*the worst situation maybe TLE,because the quickSort the worst situation need O(n^2)*/int minx = 1<<30,ans = 0;for(int i = 0; i <= n; i++)//此時已有單調(diào)性(單調(diào)遞增){minx = min(minx,a[i].pos);if(a[i].pos > minx)ans = max(ans,a[i].pos-minx);}printf("%d\n",ans);return 0; }

總結

以上是生活随笔為你收集整理的小阳买水果(前缀和,单调栈,思维)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。