【Tyvj - 1305】最大子序和(单调队列优化dp)
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                【Tyvj - 1305】最大子序和(单调队列优化dp)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                題干:
輸入一個長度為n的整數序列,從中找出一段不超過M的連續子序列,使得整個序列的和最大。
 例如?1,-3,5,1,-2,3
 當m=4時,S=5+1-2+3=7
 當m=2或m=3時,S=5+1=6
輸入格式
第一行兩個數n,m
 第二行有n個數,要求在n個數找到最大子序和
輸出格式
一個數,數出他們的最大子序和
提示
數據范圍:
 100%滿足n,m<=300000
樣例數據
| 6 4 1 -3 5 1 -2 3 | 7 | 
解題報告:
dp[i]表示到第i個數的不超過m的最大連續子段和,sum[i]表示i的前綴和
 dp[i]=max(sum[i]-sum[k])(i=> k >=i-m),所以要找在窗口內的最小的sum[k],因此用單調隊列優化一下。
然后這里dp不用開數組了,你直接拿個ans記錄一下最大值就行,因為更新過一次之后就沒有用過。(當然你也可以最后掃一遍dp數組輸出最大值)
? ?注意你要用的是sum[i]-sum[? (i-m+1)?-1],所以你第一個while要寫成<i-m,而不是i-m+1。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 3e5 + 5; ll a[MAX],sum[MAX],ans; int n,m; deque<ll> dq; int main() {ans = -99999999;cin>>n>>m;for(int i = 1; i<=n; i++) scanf("%lld",a+i),sum[i] = sum[i-1] + a[i];dq.push_back(0); for(int i = 1; i<=n; i++) {while(!dq.empty() && dq.front() < i-m) //注意這里不能用dq.size()判斷!因為只能說明雙端隊列中有m個元素,但是不能證明就是連續的m個,有可能隊首元素是a[1]呢?(因為有可能中間的元素都在下一個while中被pop了) dq.pop_front();while(!dq.empty() && sum[dq.back()] >= sum[i]) dq.pop_back();dq.push_back(i); ans = max(sum[i] - sum[dq.front()],ans);}printf("%lld\n",ans);return 0 ; } /* 6 4 1 -3 5 1 -2 3 1 -2 3 4 2 5 */在此處交題http://www.joyoi.cn/problem/tyvj-1305
總結
以上是生活随笔為你收集整理的【Tyvj - 1305】最大子序和(单调队列优化dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 办信用卡哪家银行好 信用卡哪个银行好办
- 下一篇: 信用卡审核不通过会有提示吗 信用卡没有通
