首页 > 编程语言 > 详细

算法笔记--单调队列优化dp

时间:2018-07-12 11:09:28      阅读:301      评论:0      收藏:0      [点我收藏+]

单调队列:队列中元素单调递增或递减,可以用双端队列实现(deque),队列的前面和后面都可以入队出队。

单调队列优化dp:

问题引入:

dp[i] = min( a[j] ) ,i-m < j <= i

普通的做法是O(nlogn),但是当n很大是,这个复杂度就不行了,考虑用单调队列优化来达到O(n)。

单调队列优化dp时维护的一般都是两个值{ id(下表),value(值)},且它们都保持单调。

对于这个问题,我们维护一个两个值都单调递增的序列。

查询:队首不断删除,直到队首下标大于等于i - m + 1,队首就是答案。

插入:因为要保证下标单调递增,所以从队尾加入元素a[i],因为又要保证值单调递增,所以我们不断删除队尾大于a[i]的元素,直到队尾小于a[i]或者队列为空,然后在队尾添加a[i]。

为什么我们能直接删除队尾大于a[i]的元素呢?

因为队尾删除的那些元素下标比a[i]小且值比a[i]大,如果这些元素可以是答案,那么a[i]肯定比他们好,所以这些值不会对答案产生贡献,所以直接删除就好了。

最后,每个元素最多入队一次,出队一次,复杂度为O(n)。

例题:POJ 2823

代码:

技术分享图片
#include<iostream>
#include<cstdio>
#include<queue>
#include<deque>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head

const int N = 1e6 + 5;
int ans1[N], ans2[N];
int main() {
    int n, k, x;
    scanf("%d %d", &n, &k);
    deque<pii>mn, mx;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &x);
        while(!mn.empty() && mn.back().se >= x) mn.pop_back();
        mn.pb(mp(i, x));
        while(!mn.empty() && mn.front().fi < i-k+1) mn.pop_front();
        ans1[i] = mn.front().se;
        while(!mx.empty() && mx.back().se <= x) mx.pop_back();
        mx.pb(mp(i, x));
        while(!mx.empty() && mx.front().fi < i-k+1) mx.pop_front();
        ans2[i] = mx.front().se;
    }
    for (int i = k; i <= n; i++) printf("%d%c", ans1[i], " \n"[i==n]);
    for (int i = k; i <= n; i++) printf("%d%c", ans2[i], " \n"[i==n]);
    return 0;
}
View Code

 

算法笔记--单调队列优化dp

原文:https://www.cnblogs.com/widsom/p/9298088.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!