当前位置:首页 >> 技术栈专业化分层 >> 【Tyvj - 1305】最大子序和(单调队列优化dp),windowsxp系统盘

【Tyvj - 1305】最大子序和(单调队列优化dp),windowsxp系统盘

cpugpu芯片开发光刻机 技术栈专业化分层 6
文件名:【Tyvj - 1305】最大子序和(单调队列优化dp),windowsxp系统盘 【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

样例数据 输入样例 #1输出样例 #1 6 41 -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_pairusing 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 41 -3 5 1 -2 31 -2 3 4 2 5*/

在此处交题http://www.joyoi.cn/problem/tyvj-1305

协助本站SEO优化一下,谢谢!
关键词不能为空
同类推荐
«    2026年1月    »
1234
567891011
12131415161718
19202122232425
262728293031
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言
文章归档
网站收藏
友情链接