题目大意
大体思路
由数据范围和大概的题意不难知道这题用的是单调队列。
但是好多大佬直接用 deque 秒杀了这题,但是其实可以有更优的方法,于是 给出一种不用 STL,且空间小、代码简短的近似于单调队列模板的方式。
定义 h e a d head head 和 t a i l tail tail 分别维护这个单调队列的头和尾。每次读入的循环里保持 k k k 的间距,按照题意模拟即可。最后的答案即 t a i l − h e a d tail - head tail−head。
注意点:
-
第一个 while 循环完后 q h e a d q_{head} qhead 依然是不小于 l l l 的,因此后面一定要
head--
! -
当一次循环开始我们要求左端点时, i − k + 1 i - k + 1 i−k+1 必须对 1 1 1 取最大值,不然如果 i < k i < k i<k,左端点就会是负数,不满足题意。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
inline ll read() {
ll x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); }
return x * f;
}
int n, k, head = 1, tail = 0, q[1000007];
ll a[1000007];
int main() {
n = read(), k = read();
for(int i = 1; i <= n; i++) {
a[i] = read();
int l = max(1, i - k + 1), r = i;
while(head < tail && q[head] < l) head++; head--;
while(head < tail && a[q[tail]] <= a[i]) tail--;
q[++tail] = i;
if(i >= k) printf("%d\n", tail - head);
}
return 0;
}