单调队列与DP

      以前以为单调队列只能求解区间最值的问题,没想到还能用于dp的优化,使循环的维度直接减去1维,将原先O(n³)复杂度的方程优化成O(n²)。最近几天刷了几道相关的题目,遂小小的总结一下以防以后忘掉。

  首先,单调队列是一种单调递增或者单调递减的队列(如1、3、5、7、9是单调递增的队列)。对于单调队列的操作主要有三种:插入(从队尾插入一个新元素)、取最值(取队头的元素)、删除(从队头开始删除已经失效的元素)。由于操作较简单,一般采用一维数组的方式来存储队列,用head、tail分别表示队头和队尾。操作的代码如下(以单调递增队列为例,即队首为最小值)。

    int q[100];
    int head = 0, tail = 0, x;
    //插入
    while(head < tail && q[tail-1] > x) tail--;
    q[tail++] = x;
    //取值
    printf("%d\n", q[head]);
          但是,单调队列不是对所有的状态方程都有效,只有形如dp[i] = max{f[k]}+g[i]或dp[i] = min{f[k]}+g[i],其中(k < i && g[i]与k无关)的方程才能进行优化,优化对象为f[k]。

          例如,方程dp[i] = max{dp[j]}+i+j,其中(0<=i < 100, 0 <= j < i)。变换方程式,得dp[i] = max{dp[j]+j}+i。当i=1时,j只可取0,即dp[1] = dp[0]+1+0;当i=n时,j可取0-(n-1)。即i每增加1,j的范围也增加1。当i=n时,向队列中加入元素(dp[n-1]+n-1),这样每次取出的队头元素再加上i,即为dp[i]的值。代码如下

    dp[0] = 0;
    for(int i = 1; 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值