$Poj3017\ Cut\ The\ Sequence$ 单调队列优化$DP$
Description
给定一个长度为N的序列 A,要求把该序列分成若干段,在满足“每段中所有数的和”不超过M的前提下,让“每段中所有数的最大值”之和最小.
N<=105,M<=1011,0<Ai<=106
Sol
一篇比较清楚的题解 $OvO$
$F[i]$表示把前$i$个数分成若干段,满足每段中所有数之和不超过$M$的前提下,各段的最大值之和的最小值
不难推出转移方程:

但是直接枚举$j$的做法是$O(N^{2})$的,显然过不去,还要优化.
DP转移优化的指导思想是及时排除不可能的决策,保持候选集合的高度有效性和秩序性.
本着这个思想我们来思考怎样的j可能成为最优解.
$j$要满足一下两个条件之一才有可能成为最优解:
1.$A[j+1]=max\ Ak$
2.$\sum_{k=j}^{i}Ak>M$ 即: j是满足区间和小于等于$M$的最小下标
证明,反证法:
假设以上条件都不成立
由以上条件可知$[j,i]$和$[j-1,i]$的区间都是满足题意(区间和$<=M$)且区间最大值相等
又因为显然有$F[j-1]$≤$F[j]$
所以$F[j-1]+max{Ak}<F[j]+max{Ak}$
$j-1$比$j$更优,$j$不可能是最优的
第$1$个条件显然可以维护一个$j$递增,$Aj$递减的单调队列
Code
#include<iostream>
#include<cstdio>
#define il inline
#define Rg register
#define go(i,a,b) for(Rg int i=a;i<=b;i++)
#define yes(i,a,b) for(Rg int i=a;i>=b;i++)
#define ll long long
using namespace std;
il int read()
{
int x=,y=;char c=getchar();
while(c<''||c>''){if(c=='-')y=-;c=getchar();}
while(c>=''&&c<=''){x=(x<<)+(x<<)+c-'';c=getchar();}
return x*y;
}
int n,a[],q[],f[];
ll m,s[];
int main()
{
n=read(),scanf("%lld",&m);
go(i,,n){a[i]=read();s[i]=s[i-]+a[i];if(a[i]>m){printf("-1");return ;}}
int nw=,h=,t=;
go(i,,n)
{
while(s[i]-s[nw-]>m)nw++;
while(h<=t && q[h]<nw)h++;
while(h<=t && a[q[t]]<=a[i])t--;
q[++t]=i;
f[i]=f[nw-]+a[q[h]];
go(j,h,t-)f[i]=min(f[i],f[q[j]]+a[q[j+]]);
}
printf("%d\n",f[n]);
return ;
}
随机推荐
- 13 -1 BOM和定时器
一 BOM JavaScript基础分为三个部分: ECMAScript:JavaScript的语法标准.包括变量.表达式.运算符.函数.if语句.for语句等. DOM:文档对象模型,操作网页上的元 ...
- HDU - 6534 Chika and Friendly Pairs
这个题其实也是很简单的莫队,题目要求是给一个序列,询问l-r区间内部,找到有多少对答案满足 i < j 并且 | a[ i ] -a[ j ] | <=k 也就是有多少对,满足差值小于k的 ...
- oracle函数 exp(y)
[功能]返回e的y次幂(e为数学常量) [参数]y,数字型表达式 [返回]数字 [示例] select exp(3),exp(0),exp(-3) from dual; 返回:20.0855369,1 ...
- 自定义element树表格图标
如下图: css代码: /deep/.el-icon-arrow-right:before { content: "\e6d9"; } /deep/.el-table__expan ...
- angular ui 路由传参
1. ui-sref.$state.go 的区别 ui-sref 一般使用在 <a>...</a>: $state.go('someState')一般使用在 controlle ...
- [C#] 调试silverlight的时候,总是报“向占位程序传送了空的索引指针”
这是由于visual studio在调试silverlight的时候,必须和ie一起工作. 按照以下步骤可以把ie设为visual studio的默认浏览器(不用修改操作系统的默认浏览器): 1) 在 ...
- setTimeout与setInterval有何区别?
①setTimeout和setInterval的语法相同.它们都有两个参数,一个是将要执行的代码字符串,还有一个是以毫秒为单位的时间间隔,当过了那个时间段之后就将执行那段代码. ②不过这两个函数还是有 ...
- Python--day42--mysql数据库--mysql前言
- python基础十四之匿名函数
匿名函数 处理简单问题的简化函数,关键字lambda. # 格式:函数名 = lambda 参数:返回值 anonymity = lambda s: s ** 0.5 print(anonymity( ...
- Css布局常用 1.盒子内容局中 2. 物理一像素 3.倒三角形 绘制
布局 对象属性 new Person('') 原型链 (创建对象.使用对象中的属性,如果没有那么就去原型找) new Person() Person{ name:'', getname( ...