描述

  把一个正数列 $A$分成若干段, 每段之和 不超过 $M$, 并且使得每段数列的最大值的和最小, 求出这个最小值。

题目链接

题解

  首先我们可以列出一个$O(n^2)$ 的转移方程 : $F_i = \min( F_j + \max( A_k ) )  $ $ j < i  \&\&   j < k <= i$

  然后我们可以考虑毒瘤优化。

  按照lyd的书中的思路, j 想要成为 可能的最优决策, 必须满足两个条件之一 :

  1.   j 是最小的使    $\sum\limits_{k= j + 1}^ia_k  <= M$成立的数
  2. $\forall k \in [j + 1, i] , A_j>A_k$

  可以用反证法来证明。

  对于第一个条件,可以在$O(n)$ 时间内求出所有的$j$, 并进行决策。

  接着构造一个单调队列, 满足 $j$ 递增, $A_j$ 递减 ——  若 $A[ j_1]< A[j _2]$则不满足第二个性质, 只能由让$j$ 满足第一个条件, 将$ j_1$弹出队列即可。

  查询在队列中的最优决策时, 队首不一定就是最有决策, 需要用 STL- set 来储存队列中的 $ F_j + \max(A_k)$ $ j < i && j < k <=i$, 查询set中的最小值并更新答案。

  而 $F_j$是已经求出的,最后的问题就是如何快速求出 $\max(A_k)$ 。 单调队列中的 元素 $j$的下一个元素就是要求的$\max(A_k)$。 因为单调队列中$A_j$是递减的。  

  另外还有许多细节需要注意,看代码吧(

代码

 #include<cstring>
#include<cstdio>
#include<algorithm>
#include<set>
#define rep(i,a,b) for( int i = (a); i <= (b); ++i )
#define per(i,a,b) for( int i = (a); i >= (b); --i )
#define rd read()
using namespace std;
typedef long long ll; const int N = 2e5 + 1e4; int n, a[N], q[N];
ll f[N], m; set<ll>st; int read() {
int X = , p = ; char c = getchar();
for(; c > '' || c < ''; c = getchar() ) if( c == '-' ) p = -;
for(; c >= '' && c <= ''; c = getchar() ) X = X * + c - '';
return X * p;
} inline ll cmin( int A ,int B ) {
return A < B ? A : B;
} int main()
{
n = rd;
scanf("%lld",&m);
rep( i, , n ) a[i] = rd;
f[] = ;
int low = , l = , r = ;
ll sum = ;
set<ll>::iterator it;
rep( i, , n ) {
sum += a[i];
while( sum > m ) sum -= a[++low]; // 求出最小的j使得连续一段和不超过m
if( low >= i ) return printf("-1\n"), ;
while( l <= r && q[l] < low ) {//检验队首是否满足连续和不超过m
if( l < r ) st.erase( f[q[l]] + a[q[l+]]);//队列中删除被弹出的答案
l++;
}
while( l <= r && a[q[r]] <= a[i] ) {//使队列递减
if( l < r ) st.erase( f[q[r - ]] + a[q[r]]);
r--;
}
q[++r] = i;
if( l < r ) st.insert( f[q[r - ]] + a[q[r]]);//加入i,这样才能更新出可行的最优答案
f[i] = f[low] + a[q[l]];
if( st.size() ) {
it = st.begin();
f[i] = cmin( *it, f[i]);
}
}
printf("%lld\n", f[n]);
}

poj3017 Cut the Sequence 单调队列 + 堆 dp的更多相关文章

  1. $Poj3017\ Cut\ The\ Sequence$ 单调队列优化$DP$

    Poj   AcWing Description 给定一个长度为N的序列 A,要求把该序列分成若干段,在满足“每段中所有数的和”不超过M的前提下,让“每段中所有数的最大值”之和最小. N<=10 ...

  2. [poj3017] Cut the Sequence (DP + 单调队列优化 + 平衡树优化)

    DP + 单调队列优化 + 平衡树 好题 Description Given an integer sequence { an } of length N, you are to cut the se ...

  3. 【优化】单调队列与dp

    笔者大概看了一下单调队列对于DP的优化,故撰此文,望有帮助. (dp还是推式子难啊qwq) 例题1. 题目大意:在n个数的序列中,选择数字,使得其连续不超过k个数,且和最大. 本题的方程相对好推:设d ...

  4. 【转】单调队列优化DP

    转自 : http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列是一种严格单调的队列,可以单调递增,也可以单调递减.队 ...

  5. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

  6. bzoj1855: [Scoi2010]股票交易--单调队列优化DP

    单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w ...

  7. 【HDU 3401 Trade】 单调队列优化dp

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3401 题目大意:现在要你去炒股,给你每天的开盘价值,每股买入价值为ap,卖出价值为bp,每天最多买as ...

  8. hdu3401:单调队列优化dp

    第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...

  9. Parade(单调队列优化dp)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others)    ...

随机推荐

  1. Linux系统下MongoDB的简单安装与基本操作

    这篇文章主要介绍了Linux系统下MongoDB的简单安装与基本操作,需要的朋友可以参考下   Mongo DB ,是目前在IT行业非常流行的一种非关系型数据库(NoSql),其灵活的数据存储方式,备 ...

  2. Bogart gData.vb

    Imports System Imports System.Data Imports System.Data.OleDb Imports Microsoft.VisualBasic Imports S ...

  3. 本地同时安装python2和python3时pip报错

    引言: 安装完成后,想测试一下两个版本的pip是否都可以正常工作,结果python3的能正常工作,但是pip2 --version就会报错,报错信息如下: Traceback (most recent ...

  4. C++官方文档-常量成员函数

    #include <iostream> using namespace std; class MyClass { public: int x; static int n; const in ...

  5. OpenCL 归约 1

    ▶ 照着书上的代码,写了几个一步归约的计算,只计算一步,将原数组归约到不超过 1024 个工作项 ● 代码 // kernel.cl __kernel void reduce01(__global u ...

  6. 0_Simple__simpleCooperativeGroups

    ▶ 协作组,CUDA9.0 的新特性 ▶ 源代码,如何获得协作组的编号? #include <stdio.h> #include "cuda_runtime.h" #i ...

  7. linux 基本。。

    一. 将磁盘分区挂载为只读 这一步很重要,并且在误删除文件后应尽快将磁盘挂载为只读.越早进行,恢复的成功机率就越大. 1.  查看被删除文件位于哪个分区 [root@localhost  ~]# mo ...

  8. 模拟Vue之数据驱动1

    一.前言 Vue有一核心就是数据驱动(Data Driven),允许我们采用简洁的模板语法来声明式的将数据渲染进DOM,且数据与DOM是绑定在一起的,这样当我们改变Vue实例的数据时,对应的DOM元素 ...

  9. 没有装delphi软件则须修改程序的Uses单元,去掉QDialogs qtintf.dll

    转: 花了几天的功夫,终于完成了一个delphi调用webservice(C#)的任务,发现了好多问题,不过还是解决了,和大家分享一下.首先,就是调用时一个问题,如果你的webservice没有数据库 ...

  10. js获取或判断任意数据类类型的通用方法(getDataType)和将NodeList转为数组(NodeListToArray)

    function getDataType(any){ /* (1) Object.prototype.toString.call 方法判断类型: 优点:通用,返回"[object Strin ...