POJ Cut the Sequence 单调队列优化DP入门题
2012-05-23 22:49
423 查看
Cut the Sequence
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
Sample Output
Hint
Use 64-bit integer type to hold M.
Source
POJ Monthly--2006.09.29, zhucheng
Time Limit: 2000MS | Memory Limit: 131072K | |
Total Submissions: 6478 | Accepted: 1780 |
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
POJ Monthly--2006.09.29, zhucheng
/* * File: main.cpp * Author: hit-acm * * Created on 2012年5月22日, 下午11:44 */ #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define MIN(A,B) (A<B)?A:B /* * 此题的状态转移方程是很容易写的出来的,dp[i]=min(dp[j)+max(num[j+1->i])]),(sum(num[j+1->i])<=M); * 很明显是个n^2的DP,看一下数据范围必然超时,我们不得不想一下如何去优化此dp,使其复杂度变为至少是 * nlgn级别的,如何去优化成为了一个难题。以我原来的知识是没有任何思路的。现在我能想的就是学习一种新 * 的思想,就是用单调队列优化。看了很多神人的讲解之后,以此题作为入门学习的题目来进行学习。 * 我们拿输入來举例: * 8 17 * 2 2 2 8 1 8 2 1 * 单调队列的变化形式为: * 第一个元素插入后:2 * 第二个元素插入后:2 * 第三个元素插入后:2 * 第四个元素插入后:8 * 第五个元素插入后:8 1 * 第六个元素插入后:8 * 第七个元素插入后:8 2 * 第八个元素插入后:8 2 1 * * 那么如何优化呢? * 现在我们先证明一个结论: * 有x<y,必然有:dp[x]<=dp[y] *(对于这个是很容易理解的,对于y的任何合法分组,x都可以通过 * 构造,形成与其对应的分组。从而保证dp[x]<=dp[y]恒成立。 * )。那么如果我们不考虑任意段的和不超过M这个限制条件的话, * 我们就可以利用dp[1]依次更新dp[3]一旦成功就可以直接break掉 * 而不必,全部都更新一次。 * * 关键是代码如何实现呢? * 我们可以设置一个st代表恰好满足: * sum[st,i]<=M.同时对单调队列进行更新,使过时的区间最大值消失 * 那么用:dp[i]=dp[st-1]+当前单调队列的最大值,来更新但前的DP * 那么这就是结果么?不是的。比如4 5 3 M为 10.这种情况 * dp[1]=4, dp[2]=5,dp[3]=dp[2]+3=8,如果按照上式就是: * dp[3]=dp[1]+5=9. * 为什么会出现这种情况呢? * 实际上对于单调队列中的情况如: * 8 2 1时。 * 我们可以保证的是: * 8-2 ,2-1之间的满足。 * 当x<y时,dp[x]+当前队列的最大值<=dp[y]+当前队列的最大值 * 我们已经证明了:当x<y时,dp[x]<dp[y]; * 又由于当前队列的最大值是相同的,因此不等式满足。 * 因此,我们需要把单调队列里的所有备选方案全部拿出来对结果 * 进行更新,那么得出的就是最优解。 */ const int MAX = 100011; long long a[MAX]; long long dp[MAX]; long long sum[MAX]; int p[MAX]; int start, end; void insert(int x) { if (start > end) { start = end = 1; p[start] = x; return; } while (start <= end && a[p[end]] <= a[x]) end--; p[++end] = x; } void update(int st) { while (start <= end && st > p[start]) start++; } void init() { start = 1; end = 0; } int main() { int n; long long M; while (scanf("%d%lld", &n, &M) == 2) { init(); sum[0] = 0; dp[0] = 0; int st = 1; bool flag = false; for (int i = 1; i <= n; i++) { scanf("%lld", &a[i]); if (!flag && a[i] > M) { flag = true; } sum[i] = sum[i - 1] + a[i]; insert(i); while (sum[i] - sum[st - 1] > M) { st++; } update(st); dp[i] = dp[st - 1] + a[p[start]]; for (int j = start; j < end; j++) { dp[i] = MIN(dp[i], dp[p[j]] + a[p[j + 1]]); } } if (flag) { printf("-1\n"); } else { printf("%lld\n", dp ); } } return 0; }
相关文章推荐
- Poj 3017 Cut the Sequence (DP,单调队列优化,数据结构优化)
- poj 3017 Cut the Sequence dp+单调队列优化
- POJ - 3017 Cut the Sequence : 单调队列优化dp
- POJ 3017 Cut the Sequence (单调队列优化DP)
- POJ 3017 Cut the Sequence 【DP+单调队列优化+平衡树】
- POJ-3017 Cut the Sequence(DP单调队列优化 + 平衡树)
- poj 3017 Cut the Sequence(dp单调队列优化)
- POJ - 3017 Cut the Sequence(单调队列+dp)
- POJ_3017 Cut the Sequence 单调队列+dp+BST
- POJ 3017 Cut the Sequence(DP + 单调队列优化 + 平衡树)
- POJ 3017 Cut the Sequence(dp+单调队列)
- poj 3017 Cut the Sequence(DP+单调队列)
- poj 3017 Cut the Sequence(单调队列优化 )
- Cut the Sequence,Sequence Partitioning,POJ3017,POJ3245,用单调队列优化的DP
- poj3017 Cut the Sequence 单调队列优化dp 好题!
- poj 3017 Cut the Sequence(DP+单调队列+set)
- Cut the Sequence (单调队列优化DP)
- [poj3017] Cut the Sequence (DP + 单调队列优化 + 平衡树优化)
- poj 2373 Dividing the Path(dp+单调队列优化)
- POJ 2373 (Dividing the Path)单调队列优化DP