單調佇列或單調棧的學習及認識

2021-07-11 22:01:49 字數 2548 閱讀 3392

。。。顧名思義,資料是具有某方面的單調性質的(單增或單減等)。單調佇列一般是用於優化動態規劃方面問題的一種特殊資料結構,且多數情況是與定長連續子區間問題相關聯。

1.雙端佇列deque

雙端佇列是一種線性表,遵守先進先出的原則。其支援下面四種操作:

(1)從隊首刪除

(2)從隊尾刪除

(3)從隊尾插入

(4)查詢線性表中任一元素的值

2.單調佇列
單調佇列是種特殊雙端佇列,其內部元素具有單調性。最常用的是最大佇列與最小佇列,其內部元素分別單增或單減。

有如下操作:

(1)插入:若新元素從隊尾插入會破壞單調性,則刪除隊尾元素,直到不在破壞單調性為止,再將其加入單調佇列尾。

(2)獲取最優(max,min)值:訪問隊首元素。

1.自願者選拔

題目大意:有一群自願者陸陸續續的來排隊,隊首的人在某些時刻才會離開,每個人有乙個int型的人品值,現在就問在當前佇列中人品最大的是多少,沒有的話輸出-1.

1.c name rp 名字為name人品為rp的人排到隊尾

2.g 隊首的人出隊

3.q 詢問當前佇列中rp最高的

分析:這個就是乙個連續區間最大值的問題。這時單調佇列裡面的人出了先後順序是單增的,其rp是單減的(head to tail)。用乙個out變數記錄目前出隊了多少人,in記錄進來了多少了,

當某次詢問時,如果out <= in時,顯然輸出-1,不然就輸出隊首的人的rp值。

因為佇列裡面做調整的時候,對首的人原位置並不是第一,所以要記錄些這個每個人的原位置。這樣就可以o(n)的解決這個問題了。

const

int maxn = 1e6 + 10;

struct node

node(char c, int rp,int pos)

}p[maxn];

int main(int argc, const

char * argv)

else

if (op[0] == 'g') else

if (op[0] == 'q')else

if (op[0] == 'e') break;}}

return

0;}

2.sliding windows

題目大意:給定n,k值和n個數字,問數列中從左到右每連續k個數的最大最小值。

分析:這又是乙個定長區間的最值問題。對於區間[l, r]和[l + 1, r + 1],當上乙個區間訪問完後,刪掉a[l]是不會對後面區間的訪問產生影響的,這時位置和值都呈現出單調性了。當訪問r時,對於隊首的元素,如果不在[l,r]範圍內的話就剔除佇列,對於尾部元素則是小於a[r]的剔除佇列。

const int maxn = 1e6 + 10;

int n, m;

struct node

node(int

pos,int value)

}p[maxn];

int a[maxn];

void get_max()

}void get_min()

}int main(int argc, const char * argv)

return

0;}

3.max sum of max-k-sub-sequence

題目大意:給出乙個迴圈數列a[1]…a[n],a[1]與a[n]相鄰。然後問數列中連續不超過k個元素的最大和是多少並列印出maxsum始末位置。

分析:這題先得變換下表達方式,a[j+1] + … + a[i] = sum[i] - sum[j],sum[i]表示a[1]到a[i]的和。對於給定的i而言,ans = max(sum[i] - sum[j]) && (i - j <= k - 1),這時sum[i]是個定值,求ans的最大等同於求sum[j]的最小值i - k <= j <= i。就相當於維護定長區間的最小值問題了,每次更新答案的時候記錄下始末位置就好了。

#include 

#include

const int maxn = 1e5 + 10;

const int oo = -2099900000;

intq[maxn<<1];

ints[maxn<<1];

int nu[maxn<<1];

int n, k;

int main(int argc, const char * argv)

for (i = n + 1;i <= n + k - 1;++i)

s[i] = s[i - 1] + nu[i - n];

head = 0, tail = 0;

ans = oo;

for (i = 1;i <= n + k - 1;++i)

}if (second > n) second -= n;

printf("%d

%d%d\n", ans, first, second);

}return

0;}

單調佇列 單調棧

參考文章 單調佇列 poj 2823 給定乙個數列,從左至右輸出每個長度為m的數列段內的最小數和最大數。數列長度 n 106 m n n 106,m n n 106 m n 直接暴力求解複雜度在0 mn 可以考慮維護區間最值,單調佇列則是維護區間佇列的強大 單調佇列的定義 單調佇列實現的大致過程 1...

棧和佇列 單調佇列 單調棧

講解部落格鏈結 一 單調棧 1 什麼是單調棧?單調棧是指乙個棧內部元素具有嚴格單調性 單調遞增,單調遞減 的一種資料結構。2 單調棧的兩個性質 滿足從棧頂到棧底具有嚴格的單調性 滿足後進先出的特徵,越靠近棧底的元素越早的進棧。3 元素進棧的過程 對於當前進棧元素x 如果x 棧頂元素,x 進棧。否則 ...

單調棧 佇列學習

推薦部落格 單調棧 佇列只需滿足兩個條件即可,序列是單調的,並且符合棧和佇列的特性。實現 例如實現乙個單調遞增的棧,比如現在有一組數10,3,7,4,12。從左到右依次入棧,則如果棧為空或入棧元素值小於棧頂元素值,則入棧 否則,如果入棧則會破壞棧的單調性,則需要把比入棧元素小的元素全部出棧。單調遞減...