日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Lesson258 - 单调队列

發(fā)布時(shí)間:2023/12/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lesson258 - 单调队列 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【L258】單調(diào)隊(duì)列

258.1 隊(duì)列&棧

隊(duì)列:queue, FIFO

棧:stack, LIFO

258.2 單調(diào)隊(duì)列

258.2.1 題目描述

\qquad給定一個(gè)長(zhǎng)度為N的序列,以及一個(gè)整數(shù)K,要求找出該序列所有長(zhǎng)度為K的子段里面元素的最大值和最小值。

258.2.2 解題步驟

\qquad我們可以使用RMQ表來(lái)完成這道題目,時(shí)間復(fù)雜度為O(log?N)~O(\log N)~?O(logN)?。但是這道題數(shù)據(jù)范圍有一點(diǎn)大,所以不推薦使用。

\qquad現(xiàn)在要學(xué)一種新的方法:單調(diào)隊(duì)列,這個(gè)數(shù)據(jù)結(jié)構(gòu)可以用O(N)~O(N)~?O(N)?的時(shí)間復(fù)雜度完成這道題目。

\qquad單調(diào)隊(duì)列和數(shù)組一樣,只不過他的元素一定是從小到大或者從大到小按照順序來(lái)排列的。

\qquad我們可以維護(hù)一下這個(gè)單調(diào)隊(duì)列:

\qquad輸入樣例:1 3 -1 -3 5 3 6 7。

\qquadN=8, K=3

\qquad一開始的時(shí)候,單調(diào)隊(duì)列為空(NULL)。

\qquadstep 1:1進(jìn)入隊(duì)列 單調(diào)隊(duì)列:1

\qquadstep 2: 3進(jìn)入隊(duì)列,此時(shí)單調(diào)隊(duì)列的元素個(gè)數(shù)不超過查詢的數(shù)目K=3。 單調(diào)隊(duì)列:1 3

\qquadstep 3: -1進(jìn)入隊(duì)列,雖然此時(shí)單調(diào)隊(duì)列的元素個(gè)數(shù)不超過查詢的個(gè)數(shù)K=3,但是這個(gè)時(shí)候?qū)ξ苍?小于新加入的元素-1,由于在3出隊(duì)列的時(shí)候,-1還沒有出隊(duì)列,所以3就不會(huì)再有用了,因此3出隊(duì)列,同理,1也要出隊(duì)列。此時(shí)單調(diào)隊(duì)列只剩下一個(gè)元素了。單調(diào)隊(duì)列:-1

\qquadstep 4: -3進(jìn)入隊(duì)列,和step 3一樣,-3比-1晚一些入隊(duì)列,而且-3<-1,所以-1不會(huì)在有用了,-1出隊(duì)列。 單調(diào)隊(duì)列:-3

\qquadstep 5: 5入隊(duì)列 單調(diào)隊(duì)列:-3 5

\qquadstep 6: 3入隊(duì)列,和step 3一樣,3比5晚一些入隊(duì)列,而且3<5,所以5不會(huì)再游泳了,5出隊(duì)列。 單調(diào)隊(duì)列:-3 3

\qquadstep 7: 6入隊(duì)列 單調(diào)隊(duì)列:-3 3 6

\qquadstep 8: 7入隊(duì)列,但是這個(gè)時(shí)候單調(diào)隊(duì)列的長(zhǎng)度已經(jīng)超過了K=3,所以對(duì)首元素-3出隊(duì),單調(diào)隊(duì)列:3 6 7

\qquad降序和升序一樣,只不過是單調(diào)隊(duì)列要反一下

\qquad問題來(lái)了:最小(大)值是多少呢?

\qquad其實(shí)大家仔細(xì)觀察一下就可以發(fā)現(xiàn):對(duì)首元素每一次都是最小的,那是因?yàn)閱握{(diào)隊(duì)列的性質(zhì)所致的。所以查詢就是對(duì)手元素。

\qquad等于是只遍歷一遍元素就求出了區(qū)間的最小值,而且比RMQ方便許多,所以我推薦使用這種方法,時(shí)間復(fù)雜度為O(N)~O(N)~?O(N)?

\qquad又:單調(diào)隊(duì)列可以使用Stl里面的deque來(lái)實(shí)現(xiàn)一下,deque是雙端隊(duì)列,可以訪問兩邊的元素。但是這道題數(shù)據(jù)范圍實(shí)在是太大了,不推薦使用deque求解。

\qquad總結(jié):單調(diào)隊(duì)列就是下標(biāo)單調(diào),值也單調(diào)的隊(duì)列??梢允褂胐eque來(lái)實(shí)現(xiàn),頭文件為#include \<deque>。

258.2.3 代碼

258.2.3.1 STL實(shí)現(xiàn)代碼

#include <bits/stdc++.h> using namespace std;deque <int> q;int a[1000010];int main() {// 首先來(lái)查詢區(qū)間最小值const char newline = '\n';const char space = ' ';q.clear();int n, k;cin >> n >> k;// 輸入序列for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);for(int i = 1; i <= n; i ++){while(! q.empty() && a[q.back()] >= a[i]) // 隊(duì)列{q.pop_back();}q.push_back(i);while(i - q.front() >= k) q.pop_front();char ch = space;if(i == n) ch = newline;if(i >= k) printf("%d%c", a[q.front()], ch);}q.clear();// 接下來(lái)查詢區(qū)間最大值for(int i = 1;i <= n;i ++){while(! q.empty() && a[q.back()] <= a[i]){q.pop_back();}q.push_back(i);while(i - q.front() >= k) q.pop_front();char ch = space;if(i == n) ch = newline;if(i >= k) printf("%d%c", a[q.front()], ch);}return 0; }

258.2.3.2 手工實(shí)現(xiàn)代碼

#include <bits/stdc++.h> using namespace std;const int N = 1000010;int q[N], fr, ed; int val[N];bool empty() {return fr == ed; }void clear() {fr = ed = 0; }int main() {int n, k;cin >> n >> k;for(int i = 1; i <= n; i ++){scanf("%d", &val[i]);}clear();for(int i = 1; i <= n; i ++){while(! empty() && val[i] <= val[q[ed - 1]]) ed --;q[ed ++] = i;while(! empty() && i - q[fr] >= k) fr ++;if(i >= k) printf("%d ", val[q[fr]]);}printf("\n");clear();for(int i = 1; i <= n; i ++){while(! empty() && val[i] >= val[q[ed - 1]]) ed --;q[ed ++] = i;while(! empty() && i - q[fr] >= k) fr ++;if(i >= k) printf("%d ", val[q[fr]]);}return 0; }

總結(jié)

以上是生活随笔為你收集整理的Lesson258 - 单调队列的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。