POJ3017 Cut the Sequence
题意
Time Limit: 2000MS | Memory Limit: 131072K | |
Total Submissions: 12238 | Accepted: 3809 |
Description
Given an integer sequence { an } of length N, you are to cut the sequence into several parts every one of which is a consecutive subsequence of the original sequence. Every part must satisfy that the sum of the integers in the part is not greater than a given integer M. You are to find a cutting that minimizes the sum of the maximum integer of each part.
Input
The first line of input contains two integer N (0 < N ≤ 100 000), M. The following line contains N integers describes the integer sequence. Every integer in the sequence is between 0 and 1 000 000 inclusively.
Output
Output one integer which is the minimum sum of the maximum integer of each part. If no such cuttings exist, output −1.
Sample Input
8 17
2 2 2 8 1 8 2 1
Sample Output
12
Hint
Use 64-bit integer type to hold M.
Source
将一个由N个数组成的序列划分成若干段,要求每段数字的和不超过M,求【每段的最大值】的和 的最小的划分方法,输出这个最小的和。
分析
很久以前某搬题人出的考试题,竟然是POJ原题!还是我做的题太少了。参照Excelsior_kereo的题解。
设dp[i]为前i个数取得的最小和,那么我们可以有递推公式:dp[i]=min(dp[i],dp[j]+max(a[j+1],a[j+2],...,a[i])) ,其中j<=i 且sum[j]-sum[i-1]<=m。 由于a数组均大于0,那么可以发现数组dp必然是非递减的。 设a[j+1],a[j+2],...,a[i]中的最大值下标为k,由dp的非递减性,dp[j+1]+a[k]<=dp[j+2]+a[k]<=...<=dp[k-1]+a[k].所以我们取dp[j+1]+a[k],也就是说如果某一段到当前位置i的最大值都一样,取最靠前的即可。那么可以联想到单调队列,维护一个递减的队列,存的是符合要求的某一段的最大值。但是需要注意!队首元素不一定是最优的,由于队列的递减性质,队列中的所有元素都有可能组成最优解。所以用一棵平衡树(multiset)维护。
时间复杂度\(O(n \log n)\)
代码
#include<iostream>
#include<set>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using namespace std;
co int N=1e5+1;
int n,q[N];
ll m,a[N],f[N];
multiset<ll> s;
multiset<ll>::iterator it;
int main(){
read(n),read(m);
for(int i=1;i<=n;++i)
if(read(a[i])>m) return puts("-1"),0;
int t=1,l=0,r=0;
ll tot=0;
for(int i=1;i<=n;++i){
tot+=a[i];
while(tot>m) tot-=a[t++];
while(l<r&&q[l]<t)
if(++l<r&&(it=s.find(f[q[l-1]]+a[q[l]]))!=s.end()) s.erase(it);
while(l<r&&a[q[r-1]]<=a[i])
if(l<--r&&(it=s.find(f[q[r-1]]+a[q[r]]))!=s.end()) s.erase(it);
if(l<r) s.insert(f[q[r-1]]+a[i]);
q[r++]=i;
f[i]=f[t-1]+a[q[l]];
if(s.begin()!=s.end()) f[i]=min(f[i],*s.begin());
}
printf("%lld\n",f[n]);
return 0;
}
POJ3017 Cut the Sequence的更多相关文章
- [poj3017] Cut the Sequence (DP + 单调队列优化 + 平衡树优化)
DP + 单调队列优化 + 平衡树 好题 Description Given an integer sequence { an } of length N, you are to cut the se ...
- 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 单调队列 + 堆 dp
描述 把一个正数列 $A$分成若干段, 每段之和 不超过 $M$, 并且使得每段数列的最大值的和最小, 求出这个最小值. 题目链接 题解 首先我们可以列出一个$O(n^2)$ 的转移方程 : $F_i ...
- poj3017 Cut the Sequence[平衡树+单调队列优化]
这里已经讲得很清楚了. 本質上是決策點與區間最大值有一定關係,於是用单调队列来维护决策集合(而不是常规的),然后在决策集合中选取最小值. 然后觉得这题方法还是很重要的.没写平衡树,用优先队列(堆)来维 ...
- $Poj3017\ Cut\ The\ Sequence$ 单调队列优化$DP$
Poj AcWing Description 给定一个长度为N的序列 A,要求把该序列分成若干段,在满足“每段中所有数的和”不超过M的前提下,让“每段中所有数的最大值”之和最小. N<=10 ...
- 【题解】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:\) 这道题出的真的很好,奈何数据水啊! 这道题当时看得一脸懵逼,说二分也不像二分,说贪心也不像贪心,说搜索吧这题数据范围怎么这么大?而且这题看 ...
- Cut the Sequence
Cut the Sequence 有一个长度为n的序列\(\{a_i\}\),现在求将其划分成若干个区间,并保证每个区间的和不超过m的情况下,每个区间的最大值的和的最小值,\(0 < N ≤ 1 ...
随机推荐
- sqldeveloper 重置java.exe路径方法
sqldeveloper重新配置java.exe 1.进入D:\app\product\11.2.0\dbhome_1\sqldeveloper\sqldeveloper\bin路径下,找到sqlde ...
- NYOJ_1274_信道安全 -
别琢磨中间过程,我也整不清楚,死记住模板吧 #include <stdio.h> #include <string.h> #include <queue> usin ...
- itsdangerous
将字典进行加密.解密 通过私钥保证安全性 serializer=TimedJSONWebSignatureSerializer(私钥,过期时间) dumps(字典)=====>返回加密字符串 l ...
- Caused by: java.lang.NoClassDefFoundError: com/google/common/base/MoreObjects
环境:jdk1.8 开发工具:IDEA 说明:今天在做springboot集成swagger2的时候,在启动程序的时候,报错 报错信息: Error starting ApplicationConte ...
- C# 创建对象的方法
1.实例化方法,也就是new(): //where T:new () 表示T必须有构造函数 public static T Create<T> where T:new () { retur ...
- ireport使用
首先需要下载ireport,可到https://zh.osdn.net/projects/sfnet_ireport/releases/下载,可能打开速度有点慢,耐心等待下,里面有各个版本,可自行选择 ...
- ABAP基础一:ALV基础之ALV的整体结构
很久没摸ECC了,最近看到很多新人在捯饬ALV...中国就喜欢量产垃圾...培训,上岗...没有行业道德... 闲话不多说,开始正事: ALV很常见,在SAP非WEB的项目,没有不用的,它包含了报表和 ...
- H5离线缓存技术
HTML5提供了很多新的功能以及相应的接口,离线存储就是其中的一个,离线存储可以将站点的一些文件存储在本地,在没有网络的时候还是可以访问到以缓存的对应的站点页面,其中这些文件可以包括html,js ...
- C#图解第七章:类和继承
1.类继承 通过继承我们可以定义一个新类,新类纳入一个已经声明的类并进行扩展. 1.可以使用- 一个已经存在的类作为新类的基础..已存在的类称为基类(baseclass),新类称为派生类(derive ...
- intelij idea设置成eclipse快捷键
1.导入jar包文件: https://pan.baidu.com/s/1QSd_CY5X_dUUw74evbckXg 密码: 23rq 2.idea -->settting ---> ...