队列的应用

还是要感谢zhw。。。。

很早之前就学过队列了,但是一直都没有总结过

队列,顾名思义,和平时排队一样,先进先出

在NOIP范围内,我想把队列的应用分为3个


一,双指针维护

有一道非常经典的题:

给你n个正整数,问至少连续选多少个数,才能使它们的和不小于S?
n<=2000000
看到很直观的做法,前缀和维护加暴力寻找区间 O(n^2)
再想想,答案具有连续性。那就二分,转成判定性问题。O(nlogn) 还是超时
这明显是要一个O(n)的做法
我们假设已找到一段区间,刚好满足题目条件。我们先用他更新答案,后将左端点缩进一位,右端点继续暴力拓展
因为如果该区间满足题目要求,那右端点无论再怎么继续拓展,虽然满足条件,但都不可能成为最优
int s=1,t=0,sum=0,ans=0x3f3f3f3f;
while(1){
while(sum<s&&t<n){t++;sum+=a[t];}
if(sum>=s)ans=min(ans,t-s+1);
while(sum>=s&&s<=t){sum-=a[s];s++;}
if(t==n)break;
}

另外一道题,是NOIP2011T2选择客栈点击打开链接
满分做法,也是相同的思想

二,n条具有单调性的队列,维护集合中元素最大值
这类型的题是具有鲜明的标志性
一开始给一组数,每次取出一个最大值,按照一定操作规律操作后再放回,不断进行这个过程
当发现他进行该操作产生的数具有单调性时,加一条队列来存放
每次选取最大值时,只用比较只几个队列队首   时间复杂度O(n)
例如 NOIP2016day2t2 蚯蚓点击打开链接
每次切完的蚯蚓的长度,是具有单调性的
所以一条队列存放原来的蚯蚓,一条队列存放u/v*length的,另一条存放length-u/v*length.

三,单调队列
单调队列,顾名思义,要维护一条具有单调性的队列
例如一道题
维护以下操作:
1,将一个数x压入队列中
2,求队列中数的最大值
3,弹出队列位的数
4,求队列中的最大前缀和
操作次数Q<=100000

就用单调队列维护最大值和最大前缀和就好了
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100000+5;
int q1[N],q2[N],q3[N];
int w1[N],w2[N],w3[N];
int main()
{
	int Q;
	cin>>Q;
	int t1=0,t2=0,t3=0;
	int s1=1,s2=1,s3=1;
	int q=0;
	while(Q--){
	    int x,y;
	    cin>>x;
		
	    if(x==1){
		cin>>y;
      	q1[++t1]=y;w1[t1]=Q;
		while(y>=q2[t2]&&s2<=t2)t2--;
	     q2[++t2]=y;w2[t2]=Q;
	     if(s3<=t3)y=q3[t3]+y;
	     while(y>q3[t3]&&s3<=t3)t3--;
	     q3[++t3]=y;
	     w3[t3]=Q;	
        }
		
	    if(x==2)if(s2<=t2)cout<<q2[s2]<<endl;else cout<<0<<endl;

	    if(x==3){
	        if(w1[s1]==w2[s2])s2++;	
	        if(w1[s1]==w3[s3])s3++;
			q+=q1[s1]; 
			s1++;
         if(s1>t1)q=0;
	    }
		
	     if(x==4)if(s3<=t3)cout<<q3[s3]-q<<endl;else cout<<0<<endl;
			 
	}	
	return 0;
}
还有一道单调队列的经典题——广告印刷
点击打开链接我觉得这篇博客写的题解非常生动。。

单调队列多用于求确定区间大小的极值问题(滑动窗口),以及该极值的下标(位置)
而在二维平面中,求大小为l*r的子矩阵中极值,由于极值不具有递推性质,所以无法像求二维矩阵和一样直接计算
所以用二维滑动窗口吧,单独处理每一行,将答案拼接上去即可
单调队列在DP优化中也有着非常广泛的应用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值