poj2823滑動窗口(單調隊列)

題目傳送門

題意:給你一個長度爲n的數列,然後用一個長度爲k的窗口去框(k<n)每次保存k這個窗口中的最大值和最小值,輸出。

思路:這道題最樸素的on2的做法鐵定超時,然後我想過一個nlogn的方法,網上有人說可以過,但我t了,當時隊裏的學長講了單調隊列這個知識點,現在才補了題。思路其實很簡單,代碼有註釋,草稿紙準備好,直接看吧。

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<bitset>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define CLR(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const double PI=acos(-1.0);
const int maxn=1e6+10;
int fact[10]= {1,1,2,6,24,120,720,5040,40320,362880};
struct dian {
	int val,pos;//值   位置 
};
dian maxque[maxn],minque[maxn];//結構體模擬隊列 
int maxhead,maxtail,minhead,mintail;//遞減隊列(max) 頭 尾   遞增(max) 頭 尾 
int maxans[maxn],minans[maxn];//輸出的答案 
int main() {
	int n,k;
	cin>>n>>k;
	int x;
	for(int i=0; i<k; i++) {
		scanf("%d",&x);
		while(maxhead<maxtail&&maxque[maxtail-1].val<=x)maxtail--;//如果前一個小於當前輸入的   那當窗口從前向後移動時   肯定是選擇當前這個大的值,所以前面小的就不需要保存了 
		maxque[maxtail].val=x;
		maxque[maxtail++].pos=i;//記錄位置   爲之後窗口的移動做準備 
		while(minhead<mintail&&minque[mintail-1].val>=x)mintail--;//同理 
		minque[mintail].val=x;
		minque[mintail++].pos=i;
	}
	int cur=1;
	for(int i=k; i<n; i++) {
		minans[cur]=minque[minhead].val;//記錄答案   隊列頭保存的是最小的值 
		maxans[cur++]=maxque[maxhead].val;
		scanf("%d",&x);
		while(maxhead < maxtail && maxque[maxhead].pos <= i-k)maxhead++;//窗口移動後  位置不符合要求的pop出去 
		while(maxhead < maxtail && maxque[maxtail-1].val <= x)maxtail--;//對值進行之前做過的判斷 
		maxque[maxtail].val=x;
		maxque[maxtail++].pos=i;
		while(minhead < mintail && minque[minhead].pos <= i-k)minhead++;//同理 
		while(minhead < mintail && minque[mintail-1].val >= x)mintail--;
		minque[mintail].val=x;
		minque[mintail++].pos=i;

	}
	minans[cur]=minque[minhead].val;
	maxans[cur++]=maxque[maxhead].val;
	for (int i = 1; i < cur; ++i) {
		if (i > 1) putchar(' ');
		printf("%d", minans[i]);
	}
	printf("\n");
	for (int i = 1; i < cur; ++i) {
		if (i > 1) putchar(' ');
		printf("%d", maxans[i]);
	}
	printf("\n");
}
Sliding Window
Time Limit: 12000MS Memory Limit: 65536K
Total Submissions: 67150 Accepted: 19065
Case Time Limit: 5000MS

Description

An array of size n ≤ 106 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 positionMinimum valueMaximum value
[1  3  -1] -3  5  3  6  7 -13
 1 [3  -1  -3] 5  3  6  7 -33
 1  3 [-1  -3  5] 3  6  7 -35
 1  3  -1 [-3  5  3] 6  7 -35
 1  3  -1  -3 [5  3  6] 7 36
 1  3  -1  -3  5 [3  6  7]37

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章