POJ 2823 Sliding Window(单调队列)

本文介绍了一种利用单调队列解决多次查询连续序列最大值问题的方法,通过优化数据结构,将复杂度从O(n*n)降低到O(n),显著提升了查询效率。
/*
单调队列
适合解决的问题,多次查询k个连续序列中最大或最小值。可以将复杂度从O(n*n)缩短到O(n)。
实现模式:队列实现,只不过其中元素单调(依次增大或减小),我们假设求最大值。入队时比较队尾元素与插入元素的大小,如果队尾元素小与插入元素,则对尾元素出对,直到大于等于位置。
这样插入k个元素后,队列中队首即为最大值。继续进行第二次查询时,需要比较队首元素在原来元素中的位置,判断是否在这次查询的区间内,如果不在,则出对。使用自定义数组即可实现。
*/

#include <iostream>
using namespace std;
const int nMax = 1000010;
int s[nMax];
int n, k;
struct Queue
{
	int pos;
	int v;
	Queue(){}
	Queue(int pos, int v):pos(pos), v(v){}
}MinQueue[nMax], MaxQueue[nMax];//一个最小队列,一个最大队列
int MinLeft, MinRight;
int MaxLeft, MaxRight;
int main()
{
	//freopen("e://data.txt", "r", stdin);
	while(scanf("%d%d", &n, &k) != EOF)
	{
		if(!n || !k) continue;
		int i;
		for(i = 0;i < n; ++ i)
			scanf("%d", &s[i]);
		MinLeft = MinRight = MaxLeft = MaxRight = 0;
		//MinQueue[MinRight ++] = Queue(i, s[i]);
		for(i = 0; i < k; ++ i)//队列初始化,其实可以跟下面的合并
		{
			while(MinRight > 0 && MinQueue[MinRight - 1].v > s[i])
				MinRight --;
			MinQueue[MinRight ++] = Queue(i, s[i]);
		}
		printf("%d", MinQueue[MinLeft].v);
		for(i;i < n; ++ i)
		{
			if(MinQueue[MinLeft].pos < i - k + 1)//判断队首元素是否还在查询范围之内
				MinLeft ++;
			while(MinRight > MinLeft && MinQueue[MinRight - 1].v > s[i])//循环比较队尾元素与插入元素的大小,直到对尾元素大于等于插入元素或者队为空
				MinRight --;
			MinQueue[MinRight ++] = Queue(i, s[i]);//入队
			printf(" %d", MinQueue[MinLeft].v);
		}
		printf("\n");
		for(i = 0; i < k; ++ i)//与上面求最小值相同
		{
			while(MaxRight > 0 && MaxQueue[MaxRight - 1].v < s[i])
				MaxRight --;
			MaxQueue[MaxRight ++] = Queue(i, s[i]);
		}
		printf("%d", MaxQueue[MaxLeft].v);
		for(i;i < n; ++ i)
		{
			if(MaxQueue[MaxLeft].pos < i - k + 1)
				MaxLeft ++;
			while(MaxRight > MaxLeft && MaxQueue[MaxRight - 1].v < s[i])
				MaxRight --;
			MaxQueue[MaxRight ++] = Queue(i, s[i]);
			printf(" %d", MaxQueue[MaxLeft].v);
		}
		printf("\n");
	}
	return 0;
}


学生社团系统-学生社团“一站式”运营管理平台-学生社团管理系统-基于SSM的学生社团管理系统-springboot学生社团管理系统.zip-Java学生社团管理系统开发实战-源码 更多学生社团系统: SpringBoot+Vue学生社团“一站式”运营管理平台源码(活动管理+成员考核+经费审批) Java学生社团管理系统开发实战:SSM升级SpringBoot(招新报名+场地预约+数据看板) 基于SpringSecurity的社团管理APP(移动端签到+权限分级+消息推送) 企业级社团数字化平台解决方案(SpringBoot+Redis缓存+Elasticsearch活动搜索) 微信小程序社团服务系统开发(活动直播+社团文化墙+成员互动社区) SpringBoot社团核心源码(多角色支持+工作流引擎+API接口开放) AI赋能社团管理:智能匹配兴趣标签+活动热度预测+成员贡献度分析(附代码) 响应式社团管理平台开发(PC/移动端适配+暗黑模式+无障碍访问) 完整学生社团系统源码下载(SpringBoot3+Vue3+MySQL8+Docker部署) 高校垂直领域社团平台:百团大战系统+社团星级评定+跨校活动联盟 适用对象:本代码学习资料适用于计算机、电子信息工程、数学等专业正在做毕设的学生,需要项目实战练习的学习者,也适用于课程设计、期末大作业。 技术栈:前端是vue,后端是springboot,项目代码都经过严格调试,代码没有任何bug! 核心管理:社团注册、成员管理、权限分级 活动运营:活动发布、报名签到、场地预约 资源服务:经费申请、物资管理、文档共享 数据分析:成员活跃度、活动效果评估、社团影响力排名
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值