#P1792. 单调队列.填空题.v2

单调队列.填空题.v2

1. 例题分析

题目描述

给出 N 个整数,和一个长度值 Len ,要求在这 N 个整数中每个长度为 Len 的连续一段数中的最大值。

例如:N=8,Len=3,8个整数是: 2 5 1 1 2 4 7 1 。答案是 5 5 2 4 7 7 。

2 5 1 的最大值是 5

5 1 1 的最大值是 5

1 1 2 的最大值是 2

1 2 4 的最大值是 4

2 4 7 的最大值是 7

4 7 1 的最大值是 7

输入格式

第 1 行 2 个正整数:N , Len 。N 范围 [2...100000] ,Len 范围 [2...N];

第 2 行:N 个正整数,每个数范围 [1...1000000000]。

输出格式

一行,N-Len+1 个整数。

样例

10 5
7 2 1 4 3 8 5 4 3 2 1
7 8 8 8 8 8 5

算法改进

在上一题中,我们基于结构体实现了单调队列。队列中每一个成员都携带了两个信息:数字的值(num),对应的下标(id)。

可以进一步改进,让队列值存放原来数组的下标,有了下标,就能获得对应的值。这就避免了重复的数据(既占时间,又占内存)。这种做法,被广泛的使用。如果考试遇到填空题,基本上都是这样写的。所以,如果要应对第一轮的理论题,必须要学会这个方法。

#include<bits/stdc++.h>
using namespace std;
int x[100001],q[100001]; // q 是队列,存放的是下标 
int head,tail,i,n,len;
int main()
{
	scanf("%d%d",&n,&len);
	for(i=1;i<=n;i++)
		scanf("%d",&x[i]);

	head=tail=1; // 空队列,左闭右开 
	for(i=1;i<=n;i++)
	{
		//队尾出队列,队尾的数字如果没有新来的数字 t 大,就队尾出队列 
		while(tail>head&&__填空(1)__)
			__填空(2)__;
		
		//队首出队列,如果队首的数字和当前新来数字的下标差距超过 len,就是过期数据,就队首出队列 
		while(tail>head&&__填空(3)__)
			__填空(4)__;
		
		//入队列,队列中存放的是下标 
		q[tail++] = i;

		if(i>=len)	printf("%d ",__填空(2)__);
		// 队列长度不够 len 的时候不输出 
	}
	
	return 0;
}

填空(1) :{{ input(1) }}

填空(2) :{{ input(2) }}

填空(3) :{{ input(3) }}

填空(4) :{{ input(4) }}

填空(5) :{{ input(5) }}