其他分享
首页 > 其他分享> > 【priority_queue】滑动窗口

【priority_queue】滑动窗口

作者:互联网

题目链接

#10175. 「一本通 5.5 例 1」滑动窗口 - 题目 - LibreOJ (loj.ac)

前言

之前已经写过这道题的题解(2022GDUT寒假专题学习-1 B,F,I,J题 - blockche - 博客园 (cnblogs.com)),当时用的是 deque 模拟单调队列的方法来维护最大值,但后来突然发现其实可以直接用 priority_queue 优先队列来写,方便很多。

经过对比,两者的效率也是几乎一样的,但前者会快一点。

题目

给一个长度为 的数组,一个长为 的滑动窗体从最左端移至最右端,你只能看到窗口中的 个数,每次窗体向右移动一位,如下图:

你的任务是找出窗体在各个位置时的最大值和最小值。

image-20220304212415239

image-20220304212537410

思想

每个数和下标依次压进 priority_queue , 此时队列头就是当前窗口的最大值 or 最小值

每次比较当前 i 和队列头的下标,如果队列头已经出了滑动窗口,则删去,即i >= minn.top().second + k - 1时弹出队列头。

代码

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
#define SF ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int inf = 0x3f3f3f3f;
int main() {
    SF;
    int n, k;
    cin >> n >> k;
    vector<int> a(n);
    for (auto& x : a) cin >> x;
    priority_queue<P> maxn;
    priority_queue<P, vector<P>, greater<P>> minn;
    vector<P> ans;
    maxn.push({a[0], 0}), minn.push({a[0], 0});
    for (int i = 1; i < n; ++i) {
        maxn.push({a[i], i}), minn.push({a[i], i});
        if (i + 1 >= k) {
            ans.push_back({minn.top().first, maxn.top().first});
            while (i >= minn.top().second + k - 1) minn.pop();
            while (i >= maxn.top().second + k - 1) maxn.pop();
        }
    }
    for (auto& x : ans) cout << x.first << ' ';
    cout << '\n';
    for (auto& x : ans) cout << x.second << ' ';
    return 0;
}

标签:queue,minn,top,priority,maxn,滑动,include
来源: https://www.cnblogs.com/blockche/p/15966290.html