Featured image of post 洛谷专题记录(优先队列)

洛谷专题记录(优先队列)

板刷记录

扫描

题目描述

有一个 $1 \times n$ 的矩阵,有 $n$ 个整数。

现在给你一个可以盖住连续 $k$ 个数的木板。

一开始木板盖住了矩阵的第 $1 \sim k$ 个数,每次将木板向右移动一个单位,直到右端与第 $n$ 个数重合。

每次移动前输出被覆盖住的数字中最大的数是多少。

输入格式

第一行两个整数 $n,k$,表示共有 $n$ 个数,木板可以盖住 $k$ 个数。

第二行 $n$ 个整数,表示矩阵中的元素。

输出格式

共 $n - k + 1$ 行,每行一个整数。

第 $i$ 行表示第 $i \sim i + k - 1$ 个数中最大值是多少。

样例 #1

样例输入 #1

5 3
1 5 3 4 2

样例输出 #1

5
5
4

提示

对于 $20%$ 的数据,$1 \leq k \leq n \leq 10^3$。

对于 $50%$ 的数据,$1 \leq k \leq n \leq 10^4$。

对于 $100%$ 的数据,$1 \leq k \leq n \leq 2 \times 10^6$,矩阵中的元素大小不超过 $10^4$ 并且均为正整数。

思路

定义一个大根堆,里边放一对数,这个数的大小和位置。

我们对于每次查询,判断首元素的位置是否在[i-k+1,i]这个范围内,不符合的话就弹出来。

代码

priority_queue<pii,vector<pii>>q;

void solve(){
    int n, k;
    cin >> n >> k;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    for (int i = 0; i < n; i++) {
        q.push({a[i], i + 1});
        if (i + 1 >= k) {
            while (q.top().second <= i + 1 - k) {
                q.pop();
            }
            cout << q.top().first << endl;
        }
    }
}

求m区间内的最小值

题目描述

一个含有 $n$ 项的数列,求出每一项前的 $m$ 个数到它这个区间内的最小值。若前面的数不足 $m$ 项则从第 $1$ 个数开始,若前面没有数则输出 $0$。

输入格式

第一行两个整数,分别表示 $n$,$m$。

第二行,$n$ 个正整数,为所给定的数列 $a_i$。

输出格式

$n$ 行,每行一个整数,第 $i$ 个数为序列中 $a_i$ 之前 $m$ 个数的最小值。

样例 #1

样例输入 #1

6 2
7 8 1 4 3 2

样例输出 #1

0
7
7
1
1
3

提示

对于 $100%$ 的数据,保证 $1\le m\le n\le2\times10^6$,$1\le a_i\le3\times10^7$。

Licensed under CC BY-NC-SA 4.0
最后更新于 Oct 20, 2022 19:58 CST