單調隊列

咕咕咕咕的鴿子 MK 來填坑了……html

先看例題:P1886 滑動窗口 /【模板】單調隊列c++

注:摘要圖片爲例題中的圖片 QwQ。數組

emm,建議先看看關於單調棧的博客,便於理解單調隊列。spa

因此單調隊列就是隊列內元素具備單調性的隊列。而單調隊列的用處就是求區間內的最大/最小值。code

那麼怎麼求呢?以求區間最大值爲例,咱們不妨讓隊首爲咱們要的答案,那麼這就是一個單調遞減的隊列。htm

有一句話叫:「若是一我的比你小還比你強,那麼你就永遠沒法超越他了。」什麼意思呢?就是說,若是一個元素比你後入隊還比你大,你就永遠沒法成爲最大了,那麼你就沒用了,就能夠 退役 出隊了。而每次隊列新加入的元素確定是後入隊的,因此在入隊以前把隊尾和這個元素作比較:若比這個元素小(在求最大值的狀況下是小),那麼就把隊尾出隊,直到隊尾比這個元素大(若是比他大就可能成爲最大值)或隊列爲空,而後把這個元素入隊(從隊尾)(必定要入隊,由於在前面的 退役 出隊後你就有機會成爲最大了)。blog

你覺得這樣就結束了?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<<'\n';
	while(!qmin.empty())
	{
		cout<<qmin.front()<<' ';
		qmin.pop();
	}
    	//輸出答案
	return 0;
}
相關文章
相關標籤/搜索