洛谷 P2032 扫描 题解

P2032 扫描

题目描述

有一个 1 ∗ n 的矩阵,有 n 个正整数。

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

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

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

输入格式

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

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

输出格式

共 n − k + 1 行,每行一个正整数。

第 i 行表示第 i ∼ i + k − 1 个数中最大值是多少。

输入输出样例

输入 #1

5 3
1 5 3 4 2

输出 #1

5
5
4

说明/提示

对于 20% 的数据保证:1 ≤ n ≤ 1e3,1 ≤ k ≤ n

对于 50% 的数据保证:1 ≤ n ≤ 1e4,1 ≤ k ≤ n

对于 100% 的数据保证:1 ≤ n ≤ 2 ∗ 1e6,1 ≤ k ≤ n

矩阵中元素大小不超过 1e4。

【思路】

单调队列
手写单调队列有点双指针的意思
从第一个开始枚举
如果队首的数超出了k区间的距离限制就将队尾弹出
直到队首符合在k区间内的要求
如果队尾的值比这个要插入的值还小
那这个队尾是不可能被输出的
他比我小还比我强!这让我怎么活!所以弹出我吧!

处理完成之后
每一个k区间需要输出的值就是他的队首
因为这是一个递减的区间

【完整代码】

#include<iostream>
#include<cstdio>

using namespace std;
const int Max = 2000006;
int a[Max];
int q[Max];

int main()
{
	int n,k;
	scanf("%d%d",&n,&k);
	for(register int i = 1;i <= n;++ i)
		scanf("%d",&a[i]);
	int t = 0,w = 1;
	for(register int i = 1;i <= n;++ i)
	{
		while(t <= w && q[t] + k <= i)t ++;
		while(t <= w && a[q[w]] < a[i])w--;
		q[++ w] = i;
		if(i >= k)
			cout << a[q[t]] << endl;
	}
	return 0;
}
原文地址:https://www.cnblogs.com/acioi/p/11645666.html