$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 ;
}
随机推荐
- BUAA 623 Chem is Try!
http://oj55.bianchengla.com/problem/623/ 好久没写过题解了,昨天做了一道挺恶心的题目,贴一下代码上来.看了一下提交状况,好像我的代码挺短的了,至少我找不到比我短 ...
- HZOJ 斐波那契(fibonacci)
先说一个规律: 如图将每个月出生的兔子的编号写出来,可以发现一只兔子在哪一列他的父亲就是谁. 每列的首项可以通过菲波那契求得. 然后你就可以像我一样通过这个规律打表每个点的父亲,预处理出倍增数组,倍增 ...
- PHP中__FUNCTION__与__METHOD__的区别
你知道php中__FUNCTION__与__METHOD__的区别吗?本文通过一个小例子,为大家介绍下二者的区别,有兴趣的朋友可以参考下. PHP中__FUNCTION__与__METHOD__的 ...
- 利用mock生成随机的东西
Mock.mock({ "list|100": [ { 'id|+1': 1,//id排列 'color': '@color()',//随机颜色 'date': '@datetim ...
- python如何自动发送邮件
#coding=utf-8 import smtplib from email.mime.text import MIMEText from email.mime.application import ...
- WPF 之 DataTemplate 实例(摘抄)
- hdu 1716 排序2(dfs)
排列2 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- 教你怎么让vi和vim显示行数
首先我们来看看没有行号是多么难看. 2 再来看看有行号后的效果. 3 设置行号很简单. 我们要到命令模式下,输入set number :set number 按下回车 来看看效果 4 那么怎么关闭行号 ...
- [转]Spring 注解大全与详解
Spring使用的注解大全和解释 注解 解释 @Controller 组合注解(组合了@Component注解),应用在MVC层(控制层),DispatcherServlet会自动扫描注解了此注解的类 ...
- H3C 静态黑洞路由应用