Cut the Sequence
有一个长度为n的序列\(\{a_i\}\),现在求将其划分成若干个区间,并保证每个区间的和不超过m的情况下,每个区间的最大值的和的最小值,\(0 < N ≤ 100 000\)。
解
不难想到,设\(f_i\)表示把前i个位置划分后的所求,设s为a的前缀和,于是有
\]
关键在于这是\(O(n^2)\)递推,于是有以下结论优化
- f具有单调性
把得到\(f_i\)的方案中,去除掉第i个位置变为\(f_{i-1}\),要么不变,要么变小,而此时得到\(f_{i-1}\leq f_i\),于是得证。
- 最优决策点j必然满足其中之一
- \(\max_{k=j}^i\{a_k\}=a_j\)(即\(a_j\)大于等于\(a_{j+1},...,a_i\))
- \(s_i-s_{j-1}>m\)(即j是最小的j使\(s_i-s_j\leq m\))
对于最优决策点而言,如果前面的决策点比其更优,必然有\(s_i-s_{j-1}\leq m\),并且\(f_{j-1}+\max_{k=j}^i\{a_k\}\leq f_j+\max_{k=j+1}^i\{a_k\}\),而\(f\)本身具有单调性,为了让结果满足条件\(\max_{k=j}^i\{a_k\}= \max_{k=j+1}^i\{a_k\}\),即\(a_k\leq \max_{k=j+1}^i\{a_k\}\)。
于是当\(s_i-s_{j-1}> m\),\(a_k\geq \max_{k=j+1}^i\{a_k\}\)时,j可能为最优决策点。
因此对于即j是最小的j使\(s_i-s_j\leq m\),我们假设在第i-1个位置的j已经维护出来,而考虑第i个位置,此时多加了一个\(a_i\),如果不能满足条件,只要往后拉即可,这样可以做到\(O(n)\)。
至于\(a_j\)大于等于\(a_{j+1},...,a_i\),故如果转移到求\(f_{i+1}\),多了一个\(a_{i+1}\),如果\(a_{i+1}>a_j\),必然它就不再满足了,于是可以去除,而\(s_{i}-s_{j}\)又是一个单调的函数,于是我们可以维护单调递减的单调队列维护决策点a的单调性,并保证s的不超过范围。
现在问题在于如何快速求出决策点转移过来的值,易知对于决策点j\(f_j\)已是确定了,因为单调队列的性质,容易知道,决策点j的\(\max_{k=j+1}^i\{a_k\}\)也就是j在单调队列中的位置的下一个位置的a,根据这一性质,注意对单调队列末尾的特判即可。
参考代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#define il inline
#define ri register
#define ll long long
#define Size 100100
using namespace std;
multiset<int>S;
ll dp[Size];
int a[Size],T[Size],L,R;
template<class free>
il void read(free&);
template<class free>
il free Min(free,free);
int main(){
int n;ll m,sum(0);read(n),read(m);
for(int i(1);i<=n;++i)
read(a[i]),dp[i]=1e11;dp[0]=0,L=1,R=0;
for(int i(1),p(0);i<=n;++i){sum+=a[i];
while(sum>m)sum-=a[p+1],++p;if(p==i)return puts("-1"),0;T[R+1]=i;
while(L<=R&&T[L]<p)S.erase(S.find(dp[T[L]]+a[T[L+1]])),++L;
while(L<=R&&a[T[R]]<a[i])S.erase(S.find(dp[T[R]]+a[T[R+1]])),--R;
if(L<=R)S.erase(S.find(dp[T[R]]+a[T[R+1]])),S.insert(dp[T[R]]+a[i]),
dp[i]=*S.begin();T[++R]=i;
if(dp[p]+a[T[L]]<dp[i])dp[i]=dp[p]+a[T[L]];S.insert(dp[i]+a[i+1]);
}printf("%lld",dp[n]);
return 0;
}
template<class free>
il free Min(free a,free b){
return a<b?a:b;
}
template<class free>
il void read(free &x){
x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}
Cut the Sequence的更多相关文章
- [poj3017] Cut the Sequence (DP + 单调队列优化 + 平衡树优化)
DP + 单调队列优化 + 平衡树 好题 Description Given an integer sequence { an } of length N, you are to cut the se ...
- POJ3017 Cut the Sequence
题意 Language:Default Cut the Sequence Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 122 ...
- 【题解】Cut the Sequence(贪心区间覆盖)
[题解]Cut the Sequence(贪心区间覆盖) POJ - 3017 题意: 给定一大堆线段,问用这些线段覆盖一个连续区间1-x的最小使用线段的数量. 题解 考虑一个这样的贪心: 先按照左端 ...
- 刷题总结——Cut the Sequence(POJ 3017 dp+单调队列+set)
题目: Description Given an integer sequence { an } of length N, you are to cut the sequence into sever ...
- poj 3017 Cut the Sequence(单调队列优化DP)
Cut the Sequence \(solution:\) 这道题出的真的很好,奈何数据水啊! 这道题当时看得一脸懵逼,说二分也不像二分,说贪心也不像贪心,说搜索吧这题数据范围怎么这么大?而且这题看 ...
- 【poj3017】 Cut the Sequence
http://poj.org/problem?id=3017 (题目链接) 题意 给出一个数列要求将它分割成许多块,每块的数的和不超过m,要求每块中最大的数之和最小. Solution 这道题真的很不 ...
- POJ-3017 Cut the Sequence DP+单调队列+堆
题目链接:http://poj.org/problem?id=3017 这题的DP方程是容易想到的,f[i]=Min{ f[j]+Max(num[j+1],num[j+2],......,num[i] ...
- 【POJ3017】Cut the Sequence
题目大意:给定一个长度为 N 的序列,将序列划分成若干段,保证每段之和不超过 M,问所有段的最大值之和最小是多少. 题解:设 \(f[i]\) 表示前 i 个数满足上述条件的最优解,显然有状态转移方程 ...
- POJ 3017 Cut the Sequence
[题目链接] $O(n^2)$ 效率的 dp 递推式:${ dp }_{ i }=min\left( dp_{ j }+\overset { i }{ \underset { x=j+1 }{ max ...
随机推荐
- git 强制取消本地修改
本地的项目中修改不做保存操作,可以用到Git pull的强制覆盖,具体代码如下: git fetch --allgit reset --hard origin/master git fetch 指令是 ...
- POJ 3259 Wormholes Bellman题解
版权声明:本文作者靖心,靖空间地址:http://blog.csdn.net/kenden23/.未经本作者同意不得转载. https://blog.csdn.net/kenden23/article ...
- 微信小程序--学习的案例
一.「程序秀」 「程序秀」这个小程序非常特别,因为它是一个可以帮助别人开发小程序的小程序.它以「即速应用」这个无需代码一键生成微信小程序的开发工具为基础,为广大开发爱好者提供小程序开发的最新资讯和培训 ...
- js实现截取字符串后几位
var strs ="wdsdabcdefages" strs.substring(obj.filename.lastIndexOf("a")+1,strs.l ...
- Shell脚本 全局变量、局部变量
在不同的作用域中,同名的变量不会相互干涉,就好像 A 班有个叫小明的同学,B 班也有个叫小明的同学,虽然他们都叫小明(对应于变量名),但是由于所在的班级(对应于作用域)不同,所以不会造成混乱.但是如果 ...
- TStringGrid 实现下拉框
TStringGrid 实现下拉框比较常见的思路是在TSringGrid中嵌入一个TComboBox ,思路虽然简单,但开发起来却很麻烦,而且有时会出现不愿看到的效果.还有一种更巧的方法,是Delph ...
- sql语句创建表
create table `search_custom_mall` ( `id` ) NOT NULL PRIMARY KEY AUTO_INCREMENT, `uid` ) NOT NULL, `n ...
- XML文件定义约束
今天在做Android项目的时候,用到了XML解析,服务端返回的不是JSON,而是XML,这时候就需要我们解析XML了,当然在解析XML的时候,需要了XML文件的定义结构,任何一个文件的定义都是要遵循 ...
- 27 和为S的两个数字
0 引言 题目描述:输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 1 抽象问题具体化 举例: 序列为{1,2,3,4 ...
- NX二次开发-UFUN创建倒圆UF_MODL_create_blend
NX9+VS2012 #include <uf.h> #include <uf_modl.h> UF_initialize(); //创建块 UF_FEATURE_SIGN S ...