扫描
题目描述
有一个 $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$。