POJ 2823(单调队列)

Sliding Window
Time Limit: 12000MS   Memory Limit: 65536K
Total Submissions: 52179   Accepted: 14945
Case Time Limit: 5000MS

Description

An array of size  n ≤ 10 6 is given to you. There is a sliding window of size  k which is moving from the very left of the array to the very right. You can only see the  k numbers in the window. Each time the sliding window moves rightwards by one position. Following is an example: 
The array is  [1 3 -1 -3 5 3 6 7], and  k is 3.
Window position Minimum value Maximum value
[1  3  -1] -3  5  3  6  7  -1 3
 1 [3  -1  -3] 5  3  6  7  -3 3
 1  3 [-1  -3  5] 3  6  7  -3 5
 1  3  -1 [-3  5  3] 6  7  -3 5
 1  3  -1  -3 [5  3  6] 7  3 6
 1  3  -1  -3  5 [3  6  7] 3 7

Your task is to determine the maximum and minimum values in the sliding window at each position. 

Input

The input consists of two lines. The first line contains two integers  n and  k which are the lengths of the array and the sliding window. There are  n integers in the second line. 

Output

There are two lines in the output. The first line gives the minimum values in the window at each position, from left to right, respectively. The second line gives the maximum values. 

Sample Input

8 3
1 3 -1 -3 5 3 6 7

Sample Output

-1 -3 -3 -3 3 3
3 3 5 5 6 7

Source

POJ Monthly--2006.04.28, Ikki




题意:求窗口大小为k的最值




题解:之前这一题早就做过了,用的是线段树,准备使用RMQ,但是发现爆了空间了,最近又遇到了一个二维的RMQ,无论是线段树还是RMQ都会MLE,这里要使用一个神奇的算法啦:单调队列,之前早就有了解过,可是感觉学了一些数据结构好像用处并不明显,这里在极端情况下,单调队列就体现出优势了,他的空间,时间复杂度都是O(N),可以维护区间的RMQ



#include<cstdio>  
#include<cstring>  
#include<cstdlib>  
#include<cmath>  
#include<iostream>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<set>  
#include<queue>  
#include<string>  
#include<bitset>  
#include<utility>  
#include<functional>  
#include<iomanip>  
#include<sstream>  
#include<ctime>  
using namespace std;

#define N int(1e6+10)
#define inf int(0x3f3f3f3f)  
#define mod int(1e9+7)  
typedef long long LL;
int a[N],deq[N],mx[N];
int n, k;
void out(int s,int t)
{
	for (int i = s; i <t; i++)
		printf("%d ", a[deq[i]]);
	puts("-------------------------------");
}
void solve()
{
	int s = 0, t = 0;
	for (int i = 0; i < n; i++)
	{
		while (s < t&&a[deq[t - 1]] >= a[i])t--;
		deq[t++] = i;
		if (i - k + 1 >= 0)
		{
			mx[i - k + 1] = a[deq[s]];
			//out(s, t);
			if (deq[s] == i - k + 1)s++;
		}
		
	}
	for (int i = 0; i <= n - k; i++)
		printf("%d%c", mx[i], i == n - k ? '\n' : ' ');
}

void solve1()
{
	int s = 0, t = 0;
	for (int i = 0; i < n; i++)
	{
		while (s < t&&a[deq[t - 1]] <= a[i])t--;
		deq[t++] = i;
		if (i - k + 1 >= 0)
		{
			//out(s, t);
			mx[i - k + 1] = a[deq[s]];
			if (deq[s] == i - k + 1)s++;
		}
		
	}
	for (int i = 0; i <= n - k; i++)
		printf("%d%c", mx[i], i == n - k ? '\n' : ' ');
}


int main()
{
#ifdef CDZSC  
	freopen("i.txt", "r", stdin);
	//freopen("o.txt","w",stdout);  
	int _time_jc = clock();
#endif  


	while (~scanf("%d%d", &n, &k))
	{
		for (int i = 0; i < n; i++)scanf("%d", &a[i]);
		solve();
		solve1();
	}
	return 0;
}

/*
1
3 1
-1
-3 
5 -3
3 -3
6 3 -3
7 6 3



*/


你可能感兴趣的:(POJ 2823(单调队列))