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 ...
随机推荐
- tomcat启动后8005端口未被占用
8005端口是tomcat本身的端口,如果这个端口在启动时未被tomcat占用的话,就无法使用它自带的shutdown.sh脚本关闭tomcat 接下来我以tomcat-9.0.12为例说明 下载to ...
- 【Mac】【环境变量】
Mac配置环境变量的地方 1./etc/profile (建议不修改这个文件 ) 全局(公有)配置,不管是哪个用户,登录时都会读取该文件. 2./etc/bashrc (一般在这个 ...
- 牛客小白月赛12 I 华华和月月逛公园 Tarjan算法求隔边
题目链接:https://ac.nowcoder.com/acm/contest/392/I 题意:给你一个连通的无向图,问图的隔边有多少条 输入:N,M分别是点数和边数 之后M行每行两个正整数u,v ...
- 【Mybatis】【2】处理大于号小于号及其他特殊字符
正文: 问题:用<的时候会报错.因为是xml文件,会被识别成标签 解决方法: 原sql:SELECT * FROM TABLE T WHERE T.AGE < 10; 1,转义字符.用转义 ...
- Cassandra.yaml 配置详解
cluster_name 设置Cassandra集群的名称. 在Cassandra集群中,每一台服务器都必须具备相应的集群的名称.如果名称不一致,则当前Cassandra服务器无法加入集群. init ...
- css设置点击态样式
.rightMenu:active { background-color: rgba(46, 103, 222, 0.13); }
- 【转】阿里云免费SSL证书申请与安装使用(IIS7)
阅读目录 准备: 第一步:免费SSL证书申请 第二步:证书导入 第三步:分配服务器证书 最后一步:访问测试 回到顶部 准备: 阿里云已完成备案的域名一个 回到顶部 第一步:免费SSL证书申请 登陆阿里 ...
- zk observer 节点
zk 集群中有3种节点:leader,follower,observer,其中 observer 节点没有投票权,即它不参与选举和写请求的投票. 比较 Follower 和 Observer 的代码: ...
- Python3+mitmproxy安装使用教程(Windows)
一.安装 1.1 安装mitmproxy 直接使用pip安装即可 pip install mitmproxy pip本质上会一是安装mitmproxy库的相关代码,二是安装mitmproxy.exe/ ...
- nio 序列化
1.序列化 public class SerializeUtils<T extends Serializable> { public byte[] serialize(T t) { byt ...