题意

Language:Default
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的更多相关文章

  1. [poj3017] Cut the Sequence (DP + 单调队列优化 + 平衡树优化)

    DP + 单调队列优化 + 平衡树 好题 Description Given an integer sequence { an } of length N, you are to cut the se ...

  2. 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] ...

  3. poj3017 Cut the Sequence 单调队列 + 堆 dp

    描述 把一个正数列 $A$分成若干段, 每段之和 不超过 $M$, 并且使得每段数列的最大值的和最小, 求出这个最小值. 题目链接 题解 首先我们可以列出一个$O(n^2)$ 的转移方程 : $F_i ...

  4. poj3017 Cut the Sequence[平衡树+单调队列优化]

    这里已经讲得很清楚了. 本質上是決策點與區間最大值有一定關係,於是用单调队列来维护决策集合(而不是常规的),然后在决策集合中选取最小值. 然后觉得这题方法还是很重要的.没写平衡树,用优先队列(堆)来维 ...

  5. $Poj3017\ Cut\ The\ Sequence$ 单调队列优化$DP$

    Poj   AcWing Description 给定一个长度为N的序列 A,要求把该序列分成若干段,在满足“每段中所有数的和”不超过M的前提下,让“每段中所有数的最大值”之和最小. N<=10 ...

  6. 【题解】Cut the Sequence(贪心区间覆盖)

    [题解]Cut the Sequence(贪心区间覆盖) POJ - 3017 题意: 给定一大堆线段,问用这些线段覆盖一个连续区间1-x的最小使用线段的数量. 题解 考虑一个这样的贪心: 先按照左端 ...

  7. 刷题总结——Cut the Sequence(POJ 3017 dp+单调队列+set)

    题目: Description Given an integer sequence { an } of length N, you are to cut the sequence into sever ...

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

    Cut the Sequence \(solution:\) 这道题出的真的很好,奈何数据水啊! 这道题当时看得一脸懵逼,说二分也不像二分,说贪心也不像贪心,说搜索吧这题数据范围怎么这么大?而且这题看 ...

  9. Cut the Sequence

    Cut the Sequence 有一个长度为n的序列\(\{a_i\}\),现在求将其划分成若干个区间,并保证每个区间的和不超过m的情况下,每个区间的最大值的和的最小值,\(0 < N ≤ 1 ...

随机推荐

  1. sqldeveloper 重置java.exe路径方法

    sqldeveloper重新配置java.exe 1.进入D:\app\product\11.2.0\dbhome_1\sqldeveloper\sqldeveloper\bin路径下,找到sqlde ...

  2. NYOJ_1274_信道安全 -

    别琢磨中间过程,我也整不清楚,死记住模板吧 #include <stdio.h> #include <string.h> #include <queue> usin ...

  3. itsdangerous

    将字典进行加密.解密 通过私钥保证安全性 serializer=TimedJSONWebSignatureSerializer(私钥,过期时间) dumps(字典)=====>返回加密字符串 l ...

  4. Caused by: java.lang.NoClassDefFoundError: com/google/common/base/MoreObjects

    环境:jdk1.8 开发工具:IDEA 说明:今天在做springboot集成swagger2的时候,在启动程序的时候,报错 报错信息: Error starting ApplicationConte ...

  5. C# 创建对象的方法

    1.实例化方法,也就是new(): //where T:new () 表示T必须有构造函数 public static T Create<T> where T:new () { retur ...

  6. ireport使用

    首先需要下载ireport,可到https://zh.osdn.net/projects/sfnet_ireport/releases/下载,可能打开速度有点慢,耐心等待下,里面有各个版本,可自行选择 ...

  7. ABAP基础一:ALV基础之ALV的整体结构

    很久没摸ECC了,最近看到很多新人在捯饬ALV...中国就喜欢量产垃圾...培训,上岗...没有行业道德... 闲话不多说,开始正事: ALV很常见,在SAP非WEB的项目,没有不用的,它包含了报表和 ...

  8. H5离线缓存技术

      HTML5提供了很多新的功能以及相应的接口,离线存储就是其中的一个,离线存储可以将站点的一些文件存储在本地,在没有网络的时候还是可以访问到以缓存的对应的站点页面,其中这些文件可以包括html,js ...

  9. C#图解第七章:类和继承

    1.类继承 通过继承我们可以定义一个新类,新类纳入一个已经声明的类并进行扩展. 1.可以使用- 一个已经存在的类作为新类的基础..已存在的类称为基类(baseclass),新类称为派生类(derive ...

  10. intelij idea设置成eclipse快捷键

    1.导入jar包文件: https://pan.baidu.com/s/1QSd_CY5X_dUUw74evbckXg  密码: 23rq 2.idea -->settting ---> ...