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] $ 对我们有用:

  1. $ j $ 是满足 $ \sum^{k<i}_{k=j+1}A_k\leq M $ 的最小的 $ j $
  2. 我们的 $ 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)的更多相关文章

  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. iOS长按控件

    前言 网上看到一个button的长按控件效果不错,一个菱形从中间向两边增大,研究了下 原理 上图红色是控件上面放了视图,从上到下分别是view,normalLable,highlightLabel,b ...

  2. P1410 子序列 (动态规划)

    题目描述 给定一个长度为N(N为偶数)的序列,问能否将其划分为两个长度为N/2的严格递增子序列. 输入输出格式 输入格式: 若干行,每行表示一组数据.对于每组数据,首先输入一个整数N,表示序列的长度. ...

  3. linux文件夹作用

    linux下的文件结构,看看每个文件夹都是干吗用的/bin 二进制可执行命令 /dev 设备特殊文件 /etc 系统管理和配置文件 /etc/rc.d 启动的配置文件和脚本 /home 用户主目录的基 ...

  4. 创建微服务项目后,在谷歌、Safari等浏览器下无法访问的具体原因

    使用SpringBoot开发了一个项目,端口随机给指定了一个,如6666. 可是奇葩的现象出现了,当在谷歌浏览器地址栏中输入localhost:6666访问的时候,提示无法访问. 检查良久,发现代码也 ...

  5. python 之递归及冒泡排序

    一.递归函数 在函数内部,可以调用其他函数,如果一个函数在内部调用本身,这个函数就是递归函数 1.递归的基本原理: 每一次函数调用都会有一次返回.当程序流执行到某一级递归的结尾处时,它会转移到前一级递 ...

  6. Android数据存储之Shared Preferences共享数据存储

    Android数据存储之Shared Preferences共享数据存储 在Android中一共提供了4种数据存储方式,但是由于存储的这些数据都是其应用程序私有的,所以如果需要在其他应用程序中使用这些 ...

  7. Android 获取屏幕事件的坐标

    通常情况下我们只能获取当前Activity的画面坐标,那有时候我们需要做到一种类似于c++ hook的后台运行程序能够监听到前台用户的操作并记录下来,往往这类程序都是为自动化测试服务的. Androi ...

  8. Laravel 之Cache缓存

    写入缓存 Cache::put('key','value',10);//设置10分钟 获取缓存 Cache::get('key'); 增加缓存 Cache::add('key','value',10) ...

  9. 嵌入式cpu架构

    原文:http://www.kaixin001.com/repaste/11007221_7220618944.html### 内容: 目前主要CPU架构有ARM.X86/Atom.MIPS.Powe ...

  10. Centos7安装完成后一些小优化

    1.修改ip地址.网关.主机名.DNS等 [root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 #网 ...