POJ - 3017 Cut the Sequence : 单调队列优化dp
2017-08-04 15:03
501 查看
题目点此跳转
思路
题目意思是给你一个数组, 现在让你将整个数组划分为几个子区间,并且要保证每个子区间的元素和不大于M, 求 每个子区间的最大值 的和 的最小值。这是一道dp题, 单调队列的一个很大的应用就是可以优化某一类dp。
我们先将它当作一个纯dp题去写状态转移方程,之后再考虑使用单调队列优化。
设 f(i) 为数组A[1, , i]满足条件的每个子区间的最大值的和 的最小值, 则要求的结果即为 f(n);
那么状态转移方程为:
f(j) = min(f(i) + max(A[k])), 0 < i < k < j;
可以这样理解 ,每增加一位元素,都要从这个元素出发向左扩展出一个区间,然后算这个区间里的最值加上它前面算好的f(i), 前提是这个区间的和也不能超过M。如果直接枚举的话肯定也能出答案,但是会超时, 所以单调队列就派上用场了,我们的单调队列里可以保存对应区间范围内的最值,在每次向右滑动的时候更新这些最值,然后在dp的时候取出这些最值即可。
代码
(代码来自tsy)int n, num[maxn], q[maxn]; LL m, sum, f[maxn]; int main() { scanf("%d%lld", &n, &m); int pos = 0, head = 0, tail = 0; for(int i = 1; i <= n; ++i) { scanf("%d", &num[i]); sum += num[i]; if(num[i] > m) { puts("-1"); return 0; } while(sum > m) sum -= num[++pos]; while(head<=tail && q[head] <= pos) ++head; while(head<=tail && num[q[tail]] <= num[i]) --tail; q[++tail] = i, f[i] = INF; for(int j = head, k = pos; j <= tail; k = q[j], ++j) { f[i] = min(f[i], f[k]+num[q[j]]); } } printf("%lld\n", f ); 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 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(单调队列优化 )
- poj 3017 Cut the Sequence(DP+单调队列+set)
- POJ_3017 Cut the Sequence 单调队列+dp+BST
- Cut the Sequence,Sequence Partitioning,POJ3017,POJ3245,用单调队列优化的DP
- poj3017 Cut the Sequence 单调队列优化dp 好题!
- POJ 3017 Cut the Sequence(单调队列+set)
- Cut the Sequence (单调队列优化DP)
- POJ-3017 Cut the Sequence DP+单调队列+堆
- POJ--3017--Cut the Sequence--DP优化