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. POJ 1067: Wythoff Game【博弈】

    经典的威佐夫博奕把黄金分割常数乘以k(k=m-n)即为奇异点,此时奇异点是用小数据观察出来的,具体的数学证明,观察到黄金分割常数是无理数,再加上高斯函数[kφ]的形势将自然数分割成两个等价类很容易想到 ...

  2. 能量项链(codevs 1154)

    题目描述 Description 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子 ...

  3. COdevs 1074 食物链

    1074 食物链 2001年NOI全国竞赛  时间限制: 3 s 空间限制: 64000 KB 题目等级 : 钻石 Diamond 题目描述 Description 动物王国中有三类动物 A,B,C, ...

  4. 清清月儿.net学习技术资料网站

    原文发布时间为:2008-08-03 -- 来源于本人的百度文章 [由搬家工具导入] http://blog.csdn.net/21aspnet/

  5. 并发编程辅助工具-java.util.concurrent

    1. CountDownLatch 类似于计数器的功能,主要用于控制某个任务的执行先后顺序,可以控制某个任务在其他任务(可能是多线程的)执行完 之后,才会去执行. public static void ...

  6. Linux crontab 定时任务Demo

    # 查看定时任务 crontab -l #编辑定时任务crontab -e # 同步时间 */ * * * * /usr/sbin/ntpdate -u 127.0.0.1 # 定时删除文件 */ * ...

  7. laravel 查询构造器

    //查询构造器public function query(){ $bool = DB::table('student')->insert([ ['name' => '王五', 'age' ...

  8. jquery实现表单验证,所以的验证通过后方可提交

    <html>     <head>         <meta http-equiv="content-type" content="tex ...

  9. .Net Core下使用RabbitMQ比较完备的两种方案(虽然代码有点惨淡,不过我会完善)

    一.前言     上篇说给大家来写C#和Java的方案,最近工作也比较忙,迟到了一些,我先给大家补上C#的方案,另外如果没看我上篇博客的人最好看一下,否则你可能看的云里雾里的,这里我就不进行具体的方案 ...

  10. LightOJ1234 Harmonic Number 调和级数求和

    [题目] [预备知识] ,其中r是欧拉常数,const double r= 0.57721566490153286060651209; 这个等式在n很大 的时候 比较精确. [解法]可以在 n较小的时 ...