tyvj1305 最大子序和 【单调队列优化dp】
来源:互联网 发布:excel找出不重复数据 编辑:程序博客网 时间:2024/06/06 09:12
描述
输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大。
例如 1,-3,5,1,-2,3
当m=4时,S=5+1-2+3=7
当m=2或m=3时,S=5+1=6
例如 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个数找到最大子序和
第二行有n个数,要求在n个数找到最大子序和
输出格式
一个数,数出他们的最大子序和
测试样例1
输入
6 4
1 -3 5 1 -2 3
输出
7
备注
数据范围:
100%满足n,m<=300000
100%满足n,m<=300000
题解
我们由题设f[i]为i位置最大子段和,得到状态转移方程f[i] = max(f[i - 1],sum[i] - sum[k]); 【i - k <= m】
很明显这样做是O(n ^ 2)
对于求sum[i] - sum[k]的最大值,我们可以用单调队列优化
单调队列
单调队列,顾名思义,就是单调的队列,用以O(1)求最值
单调队列用双向队列维护,队首是最值【假设是最大】
每次我们向队尾插入一个元素时,我们若队尾的元素比它要小就将他删除,直至队列为空或者队尾元素大于插入
元素,再将其插入
例如5 3 1,我们要插入4
检查1 < 4,队列变为5 3
检查3 < 4,队列变为5
检查5 > 4,队列变为5 4
插入完成
你会发现这样的操作能满足队列一定单调,而队首就是我们要的值
但注意随着时间的推移,队首元素可能“过时”,就是超出了我们所规定的范围,这个时候就删除队首,直至满足范围
由于每个元素最多进队出队一次,所以总复杂度O(n)
那么这题就好做了,我们用一个单调队列维护前m个sum值,每次只用O(1)就可以转移方程
复杂度O(n)
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define LL long long int#define REP(i,n) for (int i = 1; i <= (n); i++)#define fo(i,x,y) for (int i = (x); i <= (y); i++)#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)using namespace std;const int maxn = 300005,maxm = 100005,INF = 1000000000;inline int read(){int out = 0,flag = 1;char c = getchar();while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}while (c >= 48 && c <= 57) {out = out * 10 + c - 48; c = getchar();}return out * flag;}int n,m,q[maxn],head,tail,sum[maxn],f[maxn];int main(){n = read(); m = read();REP(i,n) sum[i] = sum[i - 1] + read();head = tail = 0; q[head] = 0;for (int i = 1; i <= n; i++){while (i - q[head] > m) head++;f[i] = max(f[i - 1],sum[i] - sum[q[head]]);q[++tail] = i;while (tail > head && sum[q[tail]] < sum[q[tail - 1]]) q[tail - 1] = q[tail],tail--;}cout<<f[n]<<endl;return 0;}
阅读全文
0 0
- tyvj1305 最大子序和 【单调队列优化dp】
- tyvj1305 最大子序和
- 最大子序和(单调队列优化)
- hdu 2870 最大子矩阵 单调队列优化+dp
- 单调队列 和单调队列优化的dp
- 线段树和单调队列优化DP
- 单调队列优化DP
- 单调队列优化DP
- dp单调队列优化
- 单调队列--优化dp
- 单调队列优化dp
- 单调队列优化DP
- 单调队列优化DP
- 单调队列优化dp
- 关于DP的单调队列优化和斜率优化区别
- 模型化理解单调队列优化和斜率优化DP
- 单调队列-首尾相连数组的最大子数组和
- 首尾相连数组的最大子数组和【单调队列】
- ubuntu 16.04 php 安装curl方法
- 关于OkHttp3源码分析
- 提高JavaScript性能③
- [Leetcode] 463. Island Perimeter 解题报告
- mybatis 一对一,一对多
- tyvj1305 最大子序和 【单调队列优化dp】
- eclipse 创建 makefile 工程
- 【Android】Retrofit网络请求参数注解,@Path、@Query、@QueryMap...
- GitHub之新手有一套
- mt6735[SIM] smartphone开机后热插入SIM卡,卡不能被识别,但是插卡开机就可以
- freeSWITCH中动态加载模块
- servlet配置load-on-startup的作用
- 初识python
- VS Code使用