单调队列优化DP:顾名思义,就是拿单调队列对DP进行优化。可以把N维的DP降低到N-1维。
先来看一道例题:
//---------------------------------------------------------------------------------------------------------------//
输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大。(n<=300000)
例如 1,-3,5,1,-2,3
当m=4时,S=5+1-2+3=7
当m=2或m=3时,S=5+1=6
//----------------------------------------------------------------------------------------------------------------//
对于这道题,很明显可以用DP来解决,DP方程为:
f[i] = sum[i] - max(sum[j] | i-M<=j<=i)
答案为max(f[i] | 1<=i<=n)。
这样做的话,时间复杂度为O(n^2),超时。
注意到max(sum[j]),这时求静态区间的最大值,可以用RMQ进行优化。
时间复杂度为O(nlogn)=O(300000 * 18)=O(5400000)。对于本题,还可以承受。
可如果n再大一点的话,O(nlogn)的时间是无法接受的。对此,就可以用单调队列来进行优化。
对于每一个i:
1,如果sum[队首]>sum[i],则删除队首。
2,插入i
3,若对尾不在范围内(对于本题,即对尾
这样的话:就可以保证队列元素(即i)的单调性和队列优先级(即sum[i])的单调性,证明略。
如果上面还看不懂,那就看程序吧。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
所以,每当遇到形如f[i] = max or min(a[k] | p[i]<=k<=q[i]) + b[i] (q[i],p[i]单调,b[i]与k无关)这样的DP方程的时候,就可以用如上方法进行单调队列优化。