poj 3017 Cut the Sequence(单调队列优化DP)
Cut the Sequence

$ solution: $
这道题出的真的很好,奈何数据水啊!
这道题当时看得一脸懵逼,说二分也不像二分,说贪心也不像贪心,说搜索吧这题数据范围怎么这么大?而且这题看起来也实在不好DP,当时是真的满头雾水。只能说是各个都尝试一下。最后还是选了DP来做第一步突破,因为这道题可以用最优子结构来推出最优答案,也符合常规DP套路即设 $ F[i][j] $ 表示将前面 $ i $ 个数分成 $ j $ 份,但是这一道题没有说具体的份数,而且数据范围很大,所以我们直接设 $ F[i] $ 表示前 $ i $ 个数的最优答案。这个的转移方程还是比较好想的:
$ F[i]=^{\quad\quad min}_{0<j<i,\sum^{k<i}_{k=j+1}A_k\leq M}{F[j]+max{A_k } } $
这样我们发现我们得到了一种 $ n^2 $ 的做法,然后数据范围告诉我们这样还不够。我们还得优化,但是 $ wch $ 是真的不会优化了,这个式子很有单调队列的样子,但是这个 $ max{A_k } $ ,这个式子似乎无懈可击啊!(于是他看了看书,表示:考这道题我直接爆零离场算了)
我们知道一个优秀的搜索或DP一定要尽可能去避免一些没有用的状态和决策,书上说:要保持决策集合的高度有效性和秩序性。所以我们看一看我们会不会枚举了一些没有什么用的 $ F[j] $ 。我们可以分析得出只有两种 $ F[j] $ 对我们有用:
- $ j $ 是满足 $ \sum^{k<i}_{k=j+1}A_k\leq M $ 的最小的 $ j $
- 我们的 $ A_j $ 是从 $ j $ 到 $ i $ 中间最大的权值
这个其实我们静下心来想想就可以明白,如果一个数不是从它开始到第 $ i $ 个数中最大的而且它不是可枚举的最小的第 $ j $ 个数,那么它一定不是最优解,它的左边那一个 $ F[j-1] $ 一定更优,因为它比 $ F[j ] $ 小,而且最大值一样。于是我们用维护一个包含所有的高效决策的单调队列,显然 $ j $ 单调递增 $ A_j $ 单调递减。然后我们要支持及时删去对头失效的决策,然后更新队尾加元素。
然后是这一题非常神奇的一个地方:我们要得到答案还需要 $ max{A_k } $ ,这个我们可以倍增 $ ST $ 表,但是我们分析题目性质就能发现一个跟奇妙的地方,我们的单调队列里的下一个元素就是我们要求得 $ max{A_k } $ ,这个只要想一想都知道以为我们维护的是(所有的高效决策的单调队列,并且显 $ j $ 单调递增 $ A_j $ 单调递减)。
然后还有一个我想吐槽的地方(奈何这一题数据水),我们的单调队列的对头不一定就是我们的最佳决策,这也是说我们队列里 $ A_K $ 单调递增,但是我们求值的式子里还有一个 $ F[j] $ 这个东西是单调递减的!!!!所以我们不能妄下决定,我们还需要映射一个取值的数据结构,也就是我们的 $ set $ ,我们要让这两个东西同时增加元素又同时减少相应的元素。
$ code: $
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int
using namespace std;
int n; ll m;
int a[100005];
ll f[100005];
int q[100005];
multiset<ll >s;
inline ll qr(){
register char ch; register bool sign=0; ll res=0;
while(!isdigit(ch=getchar())) if(ch=='-')sign=1;
while(isdigit(ch)) res=res*10+(ch^48),ch=getchar();
return sign?-res:res;
}
int main(){
//freopen("in.in","r",stdin);
//freopen("cpp.out","w",stdout);
n=qr(); m=qr();
for(rg i=1;i<=n;++i) a[i]=qr();
rg l=1,r=0,k=1; ll tot=0;
for(rg i=1;i<=n;++i){
tot+=a[i];
while(tot>m)tot-=a[k++];
if(k>i){puts("-1");return 0;}
while(l<=r&&a[q[r]]<=a[i]){
if(r>l)s.erase(f[q[r-1]]+a[q[r]]);; --r;
}q[++r]=i; if(r>l)s.insert(f[q[r-1]]+a[q[r]]);
while(l<=r&&q[l]<k){
if(r>l)s.erase(f[q[l]]+a[q[l+1]]);; ++l;
}f[i]=f[k-1]+a[q[l]];
if(l<r)f[i]=min(f[i],*s.begin());
}printf("%lld\n",f[n]);
return 0;
}
poj 3017 Cut the Sequence(单调队列优化DP)的更多相关文章
- $Poj3017\ Cut\ The\ Sequence$ 单调队列优化$DP$
Poj AcWing Description 给定一个长度为N的序列 A,要求把该序列分成若干段,在满足“每段中所有数的和”不超过M的前提下,让“每段中所有数的最大值”之和最小. N<=10 ...
- poj3017 Cut the Sequence 单调队列 + 堆 dp
描述 把一个正数列 $A$分成若干段, 每段之和 不超过 $M$, 并且使得每段数列的最大值的和最小, 求出这个最小值. 题目链接 题解 首先我们可以列出一个$O(n^2)$ 的转移方程 : $F_i ...
- 算法笔记--单调队列优化dp
单调队列:队列中元素单调递增或递减,可以用双端队列实现(deque),队列的前面和后面都可以入队出队. 单调队列优化dp: 问题引入: dp[i] = min( a[j] ) ,i-m < j ...
- POJ 1821 Fence(单调队列优化DP)
题解 以前做过很多单调队列优化DP的题. 这个题有一点不同是对于有的状态可以转移,有的状态不能转移. 然后一堆边界和注意点.导致写起来就很难受. 然后状态也比较难定义. dp[i][j]代表前i个人涂 ...
- 单调队列优化DP——习题收集
前言 感觉可以用单调队列优化dp的模型还是挺活的,开个随笔记录一些遇到的比较有代表性的模型,断续更新.主要做一个收集整理总结工作. 记录 0x01 POJ - 1821 Fence,比较适合入门的题, ...
- 单调队列优化DP,多重背包
单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...
- 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 ...
- hdu3401:单调队列优化dp
第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...
- Parade(单调队列优化dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others) ...
- BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...
随机推荐
- CodeForces 303B Rectangle Puzzle II
题意: 给定一个靠着坐标轴长为n,宽为m的矩形和 矩形中的一个点A,求在这个矩形内部一个 长宽比为a/b的小矩形,使这个小矩形的长宽尽量大使点A在小矩形内部,并且点A尽量靠近小矩形的中心 CF的思维题 ...
- *Codeforces961G. Partitions
$k \leq n \leq 100000$,求式子$Ans=\sum_{i=1}^n w_i\sum_{j=1}^n j\binom{n-1}{n-j} \{ ^{n-j}_{k-1} \}$. 题 ...
- Python入门--14--字典
基础知识: 0.python对值没有要求,但对key有些要求,必须是非变量(变量,列表,字典) 1.在列表中使用成员资格操作符,和在字典中使用成员资格操作符,后者会更快 2.fromkeys这个函数会 ...
- postman 快捷方式--启动图标
下载,解压,安装,(此安装位置在/opt) 1.创建全局变量,也就是在任何地方都可以执行postman,不用去到安装目录,执行 : sudo ln -s /opt/postman/Postman /u ...
- css3 nth-child 与 nth-of-type 的区别
by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=1709 一.深呼吸,直 ...
- BZOJ——1614: [Usaco2007 Jan]Telephone Lines架设电话线
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1930 Solved: 823[Submit][Status][Discuss] Description ...
- python把日期转换为秒数;日期转为字符串;datetime、date
1.秒数是相对于1970.1.1号的秒数 2.日期的模块有time.datetime 3. import datetime t = datetime.datetime(2009, 10, 21, 0, ...
- win7系统使用engine进行开发报错,“未能加载文件或程序集”
http://www.gisall.com/wordpress/?p=7161 使用vs2010加 arcengine 开发winfrom应用,新建了uc,拖了几个控件后,编译,报未能加载文件或程序集 ...
- 转:Python yield 使用浅析 from IBM Developer
评注:没有看懂. 转: https://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/ Python yield 使用浅析 初 ...
- 向C#的选项卡中添加自定义窗体
一.自定义窗体的搭建 这个比较简单,添加一个WinForm窗体就行了,设置一个名字EditPanel,然后在窗体上画需要的控件. 二.将自定义窗体添加到选项卡 // 新建窗体加入到选项卡中 EditP ...