POJ 2823 Sliding Window(单调队列)

题目链接:点击打开链接

思路:单调队列入门题目

代码一:

// POJ 2823 Sliding Window 运行/限制:5532ms/12000ms 用C++交的,G++超时了
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n, k;
int a[1000005],queue[1000005];
void minQueue() {
	int head = 1, tail = 0;
	queue[head] = 1;
	for (int i = 0; i < n; i++) {
		//删除队首元素
		if (i - queue[head] == k) head++;
		//直接放在队尾
		if (head - tail == 1 || a[i] > a[queue[tail]]) {//第一个条件指的是队列为空
			queue[++tail] = i;
		}
		else {//不断删除队尾元素找到合适位置
			while (tail >= head && a[i] <= a[queue[tail]]) {
				tail--;
			}
			queue[++tail] = i;
		}
		if (i >= k - 1) {
			printf("%d%c", a[queue[head]], i == n - 1 ? '\n' : ' ');
		}
	}
}
void maxQueue() {
	int head = 1, tail = 0;
	queue[head] = 1;
	for (int i = 0; i < n; i++) {
		//删除队首元素
		if (i - queue[head] == k) head++;
		//直接放在队尾
		if (head - tail == 1 || a[i] < a[queue[tail]]) {//第一个条件指的是队列为空
			queue[++tail] = i;
		}
		else {//不断删除队尾元素找到合适位置
			while (tail >= head && a[i] >= a[queue[tail]]) {
				tail--;
			}
			queue[++tail] = i;
		}
		if (i >= k - 1) {
			printf("%d%c", a[queue[head]], i == n - 1 ? '\n' : ' ');
		}
	}
}
int main(){
	scanf("%d%d", &n, &k);
	for (int i = 0; i < n; i++) {
		scanf("%d", &a[i]);
	}
	minQueue();
	maxQueue();
    return 0;
}

代码二:

// POJ 2823 Sliding Window 运行/限制:5516ms/12000ms 用C++交的,G++超时了 
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n, k;
int a[1000005];//原序列 
int minQueue[1000005],maxQueue[1000005];//单调递减队列 单调递增队列
int minRe[1000005],maxRe[1000005];//结果 
void solve() {
	int minHead = 1, minTail = 0;//单调递减序列头、尾 
	int maxHead = 1, maxTail = 0;//单调递增序列头、尾 
	for (int i = 0; i < n; i++) {
		//处理单调递减序列 
		while (minTail >= minHead && a[i] <= a[minQueue[minTail]]) {
			minTail--;
		}
		minQueue[++minTail] = i;
		if(i - minQueue[minHead] == k) minHead++;
		//处理单调递增序列 
		while (maxTail >= maxHead && a[i] >= a[maxQueue[maxTail]]) {
			maxTail--;
		}
		maxQueue[++maxTail] = i;
		if(i - maxQueue[maxHead] == k) maxHead++;
		//存储结果 
		if(i >= k - 1){
			minRe[i] = a[minQueue[minHead]];
			maxRe[i] = a[maxQueue[maxHead]];
		}
	}
	//打印结果
	for(int i = k - 1;i < n;i++){
		printf("%d%c",minRe[i],i == n - 1?'\n':' ');
	}
	for(int i = k - 1;i < n;i++){
		printf("%d%c",maxRe[i],i == n - 1?'\n':' ');
	} 
}
int main(){
	scanf("%d%d", &n, &k);
	for (int i = 0; i < n; i++) {
		scanf("%d", &a[i]);
	}
	solve();
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值