• 单调队列


    咕咕咕咕的鸽子 MK 来填坑了……

    先看例题:P1886 滑动窗口 /【模板】单调队列

    注:摘要图片为例题中的图片 QwQ。

    emm,建议先看看关于单调栈的博客,便于理解单调队列。

    所以单调队列就是队列内元素具有单调性的队列。而单调队列的用处就是求区间内的最大/最小值。

    那么怎么求呢?以求区间最大值为例,我们不妨让队首为我们要的答案,那么这就是一个单调递减的队列。

    有一句话叫:“如果一个人比你小还比你强,那么你就永远无法超越他了。”什么意思呢?就是说,如果一个元素比你后入队还比你大,你就永远无法成为最大了,那么你就没用了,就可以 退役 出队了。而每次队列新加入的元素肯定是后入队的,所以在入队之前把队尾和这个元素做比较:若比这个元素小(在求最大值的情况下是小),那么就把队尾出队,直到队尾比这个元素大(如果比他大就可能成为最大值)或队列为空,然后把这个元素入队(从队尾)(一定要入队,因为在前面的 退役 出队后你就有机会成为最大了)。

    你以为这样就结束了?NoNoNo!我们还要在每次入队的时候判断队首是否不在这个区间里。这里只要一个if而不是循环,因为每次都这样判断可以保证最多只有一个(也就是队首)不在区间内。

    上代码吧:

    #include<bits/stdc++.h>
    using namespace std;
    int n,k,a[1000005];//原数组
    deque<pair<int,int> >d1;
    deque<pair<int,int> >d2;
    //d1,d2分别为求最大值,最小值的单调队列,队列里的第一个关键字存储值,第二个关键字存储这个元素在a[]数组中的位置(下标)
    queue<int>qmin;
    queue<int>qmax;
    //由于后面是一起做的,所以用队列存储答案(当然可以用数组)
    int main()
    {
    	cin>>n>>k;
    	for(register int i=1;i<=n;i++) cin>>a[i];//读入元素
    	for(register int i=1;i<k;i++)
    	{
        		while(!d1.empty()&&d1.back().first<a[i]) d1.pop_back();
    		while(!d2.empty()&&d2.back().first>a[i]) d2.pop_back();
    		d1.push_back(make_pair(a[i],i));
    		d2.push_back(make_pair(a[i],i));
    	}//先把前k-1个入队
    	if(k==1)//见后面的while,发现需要特判k=1的情况
    	{
    		d1.push_back(make_pair(a[1],1));
    		d2.push_back(make_pair(a[1],1));
    		qmin.push(a[1]);
    		qmax.push(a[1]);
    	}
    	while(d1.back().second<n)//表示后面还有元素
    	{
    		int xx1=a[d1.back().second+1],yy1=d1.back().second+1;
    		int xx2=a[d2.back().second+1],yy2=d2.back().second+1;
            	//分别记录两个单调队列的队尾的元素大小和在a[]里的序号
    		while(!d1.empty()&&d1.back().first<xx1) d1.pop_back();
    		while(!d2.empty()&&d2.back().first>xx2) d2.pop_back();
            	//让那些又老又弱的元素出队
    		if(!d1.empty()&&d1.front().second<yy1-k+1) d1.pop_front();
    		if(!d2.empty()&&d2.front().second<yy2-k+1) d2.pop_front();
            	//让不在区间内的元素出队
    		d1.push_back(make_pair(xx1,yy1));
    		d2.push_back(make_pair(xx2,yy2));
            	//将新元素入队
    		qmin.push(d1.front().first);
    		qmax.push(d2.front().first);
            	//存储答案
    	}
    	while(!qmax.empty())
    	{
    		cout<<qmax.front()<<' ';
    		qmax.pop();
    	}
    	cout<<'
    ';
    	while(!qmin.empty())
    	{
    		cout<<qmin.front()<<' ';
    		qmin.pop();
    	}
        	//输出答案
    	return 0;
    }
    
  • 相关阅读:
    Unique Binary Search Trees——LeetCode
    Binary Tree Inorder Traversal ——LeetCode
    Maximum Product Subarray——LeetCode
    Remove Linked List Elements——LeetCode
    Maximum Subarray——LeetCode
    Validate Binary Search Tree——LeetCode
    Swap Nodes in Pairs——LeetCode
    Find Minimum in Rotated Sorted Array——LeetCode
    Linked List Cycle——LeetCode
    VR AR MR
  • 原文地址:https://www.cnblogs.com/mk-oi/p/13610513.html
Copyright © 2020-2023  润新知