题意:

  给定含有n个元素的数列a,要求将其划分为若干个连续子序列,使得每个序列的元素之和小于等于m,问最小化所有序列中的最大元素之和为多少?(n<=105。例:n=8, m=17,8个数分别为2 2 2 | 8 1 8 |1 2,答案为12。)

思路:

  想明白一个队列+一个set就能完美解决这个问题?

  首先DP的转移式子是:dp[i]=min( dp[j] +max[j+1, i]  ),且sum[i]-sum[j]<=m,j为枚举的断开处。暴力寻找一个合适的j的复杂度为O(n2)。那么问题就在于如何寻找这个合适的j。

  先假设j的范围是(low, i],而max是随着j的增大单调不减的,则max[k,i]>=max[p,i]且k<p是肯定的。那么如果出现max[k,i]=max[p,i]且k<p的话,j=k明显更佳,因为dp[k]<=dp[p]是肯定的!那么如果出现max[k,i]>max[p,i]且k<p的话,取哪个就难说了,也是因为dp[k]<=dp[p] 。

  根据转移式子知道,j肯定是不跟i同组的,这是根据dp[j]的定义来决定的。那么j有可能的取值为low,或者为k(a[k]>a[i]),那么单调队列就形成了,队列中保存下标,表示所有a[k]>a[i]且low<=k<=i。

  但是这队列有什么用?值val可能等于队列中任一元素u,而val=dp[u]+max[u+1,i]是没有什么规律的。直接将所有val装进set中,最小的set.begin()就是我们要找的答案了。如果维护单调队列时需要删除怎么办?直接将算出来的val在set中删除。

  注意:如果队列为空,即a[i]是a[low,i]中的最大值,那么最多只能取j=low。如果low一旦改变了,队头元素也有可能改变喔~因为队头算出来的val可能是根据更小的low算出来的。由于多个val相同的情况是存在的,所以用multiset。

 //#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <deque>
#include <map>
#include <algorithm>
#include <vector>
#include <iostream>
#define pii pair<int,int>
#define back que[rear-1]
#define INF 0x7f7f7f7f
#define LL long long
#define ULL unsigned long long
using namespace std;
const double PI = acos(-1.0);
const int N=;
LL sum[N], has[N], dp[N];
int a[N], que[N], top, rear, low;
multiset<LL> sett;
LL cal(int n,LL m)
{
for(int i=; i<=n; i++)
{
if(a[i]>m) return -;
while( sum[i]-sum[low]>m ) low++; //过期的只可能在top处
while( top<rear && que[top]<=low )
sett.erase( has[top++] ); if(top<rear)
{
//队头的val有可能会改变,因为下限low提高了
sett.erase( has[top] );
has[top]=dp[low]+a[ que[top] ];
sett.insert( has[top] );
}
//插入队列先
while(top<rear && a[i]>a[ que[rear-] ] )
sett.erase( has[--rear] ); que[rear]=i; //只记下标
LL val=;
if(top^rear) val=dp[ que[rear-] ]+a[i];
else val=dp[low]+a[i]; //top=rear时,a[i]就是最大的
sett.insert( val );
has[rear++]=val;
dp[i]=*sett.begin(); //取最小
}
return dp[n];
} int main()
{
//freopen("input.txt","r",stdin);
int n;LL m;
scanf("%d%lld", &n, &m);
for(int i=; i<=n; i++) //机器
{
scanf("%d",&a[i]);
sum[i]=sum[i-]+a[i];
}
printf("%lld\n", cal(n,m));
return ;
}

AC代码

POJ 3017 Cut the Sequence (单调队列优化DP)的更多相关文章

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

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

  2. poj3017 Cut the Sequence 单调队列 + 堆 dp

    描述 把一个正数列 $A$分成若干段, 每段之和 不超过 $M$, 并且使得每段数列的最大值的和最小, 求出这个最小值. 题目链接 题解 首先我们可以列出一个$O(n^2)$ 的转移方程 : $F_i ...

  3. 算法笔记--单调队列优化dp

    单调队列:队列中元素单调递增或递减,可以用双端队列实现(deque),队列的前面和后面都可以入队出队. 单调队列优化dp: 问题引入: dp[i] = min( a[j] ) ,i-m < j ...

  4. POJ 1821 Fence(单调队列优化DP)

    题解 以前做过很多单调队列优化DP的题. 这个题有一点不同是对于有的状态可以转移,有的状态不能转移. 然后一堆边界和注意点.导致写起来就很难受. 然后状态也比较难定义. dp[i][j]代表前i个人涂 ...

  5. 单调队列优化DP——习题收集

    前言 感觉可以用单调队列优化dp的模型还是挺活的,开个随笔记录一些遇到的比较有代表性的模型,断续更新.主要做一个收集整理总结工作. 记录 0x01 POJ - 1821 Fence,比较适合入门的题, ...

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

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

  7. 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 ...

  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)    ...

  10. BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP

    BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...

随机推荐

  1. qt5.3+vs2013乱码

    解决qt5.3+vs2013乱码,在main函数之前加入 #if _MSC_VER >= 1600 #pragma execution_character_set("utf-8&quo ...

  2. 程序员必备,C#各类项目、开源项目插件资料收藏

    一.AOP框架     Encase 是C#编写开发的为.NET平台提供的AOP框架.Encase独特的提供了把方面(aspects)部署到运行时代码,而其它AOP框架依赖配置文件的方式.这种部署方面 ...

  3. Java 普通方法和构造方法的区别

    构造方法: ①方法名和 类名相同 ②在方法名的前面没有返回值类型的声明 ③在方法中不能使用return语句返回一个值 ④在创建对象时,要调用new,如:book b1=new book(); ⑤当没有 ...

  4. TCP/IP之大明邮差

    大明王朝天启四年, 清晨. 天色刚蒙蒙亮,我就赶着装满货物的马车来到了南城门, 这里是集中处理货物的地方 , 一队一队的马车都来到这里, 城头的士兵带着头盔,身披盔甲, 手持长枪, 虎视眈眈的注视这下 ...

  5. tp5 搜索之后保留分页

    当接收到参数是执行搜索 public function index($name=null){ if (isset($_REQUEST['username'])) { $name = $_REQUEST ...

  6. opengl Polygon Offset

    http://www.cnblogs.com/bitzhuwei/archive/2015/06/12/4571539.html#_label2 启用了Polygon Offset,那么到底要把立方体 ...

  7. HyperLedger Fabric 多机部署(一)

    本文参考:http://www.lijiaocn.com/%E9%A1%B9%E7%9B%AE/2018/04/26/hyperledger-fabric-deploy.html  学习. 1.准备工 ...

  8. 2018最新苹果APP上架App Store流程(超详细)

    本文转发:https://blog.csdn.net/xxw888/article/details/73618837 2018最新整理iOS app上架app详细教程 上架iOS需要一个付费688的开 ...

  9. glassfish 自定义 jaas realm

    https://www.oschina.net/translate/custom-jaas-realm-for-glassfish-3

  10. 01.html5+phonegap跨平台移动应用开发

    一.html5+PhoneGap基础知识 (1)html5介绍 HTML5是用于取代1999年所制定的 HTML 4.01 和 XHTML 1.0 标准的 HTML 标准版本,现在仍处于发展阶段,但大 ...