既然在模板庫中發了單調佇列的板子,那麼就順便把單調佇列講一講吧。(我不會說是在noip前一天攢一攢rp的~)單調佇列和單調棧的方法差不多,而且可以算是不會線段樹的oier的福音了。所以單調棧也不會的同學也來學一學吧,反正操作也是差不多的。
回歸正題~單調佇列的用途是維護乙個區間的最值的(是不是很像線段樹啊~咳咳…),一般用在求資料範圍比較大的題目中(廢話~不然暴力都過了)。其實簡單的說,只有幾句話,以維護區間最小值為例:當佇列尾部的元素大於即將進入佇列的元素時,就不斷的讓隊尾元素出列,直到隊尾元素小於即將進入佇列的元素或者隊列為空為止。然後假設我們要維護乙個區間長為m的最小值,當我們隊尾的元素在原陣列中所對應的下標減去隊首元素的下標大於等於m的時候,我們就需要把隊首元素出列。
下面是講解:首先既然是單調佇列,那麼佇列中的元素就必須要一直保持乙個單調性,不能因為入佇列的元素而打亂順序,這是通過定義上來解釋第乙個操作的;而通過佇列中元素的作用的方法來解釋就是:當進入佇列的元素進入後,通過我們的操作,佇列中的元素一定都是當前元素下標pos-m+1到pos中的元素,所以說當我們要維護最小值的時候,那麼比當前進入佇列的元素大的元素都不會對結果造成影響了,所以可以出佇列了(這裡需要好好消化一下,理解了這裡就可以簡單的寫出單調佇列了)。然後是第二個操作,也是比較好理解的,因為當隊首元素的下標與隊尾元素的下標差超過m的時候,就意味著這個元素已經不在即將處理的長度為m的區間的最小值範圍內了,也就不會對結果造成影響了,也可以出佇列了。
首先,上面講到的單調佇列是需要在隊首和隊尾出列的,所以我們還需要用到雙向佇列deque,然後就是操作了 ,實際上只要理解了上面的講解,並且在細節上加以處理,就可以了,所以直接放出**吧:
#include
using
namespace
std;
const
int maxn=2000005;
typedef
long
long ll;
typedef pairint>p;
#define fi first
#define se second
inline
void read(int &x)
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
x*=f;
}inline
void read(ll &x)
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
x*=f;
}int n,m;
ll a[maxn];
ll minn[maxn];
deque
void get_min()
q.push_back(p(a[now],now));
p top=q.back();
p fr=q.front();
if(top.se-fr.se>=m)//當隊首元素和隊尾元素的下標的差大於等於m的時候,把隊首元素出隊
minn[now]=q.front().fi;//記錄當前的最小值為隊首元素
now++;
}}int main()
get_min();
minn[0]=0;
for(int i=0;iprintf("%lld\n",minn[i] );
}}
czl的知識點整理4 線段樹
首先對於線段樹,其實與其他各種樹都是一樣的,都有著樹形的結構。接下來讓我們考慮一些問題 給出乙個陣列,要求滿足下面的操作 給定三個值x,y,z,要求吧 x,y 區間的每個數都加上z。給定兩個值x,y,要求輸出 x,y 區間的最大值 or最小值or和 如果我們用暴力做這些問題,那麼對於操作 和 每次的...
czl的知識點整理2 高斯消元
xjoi 1822 civilization 高斯消元其實在小學初中解多元一次方程的時候已經接觸過了。其實,高斯消元就是建立在方程中加減消元和乘除消元之上的。只不過,高斯消元法把這兩種方法應用於矩陣之中,使得高斯消元的複雜度達到o n 相比於真正的去解方程可是要快的多了,想一想你手解100000元一...
知識點整理
一 標準庫容器和演算法 1.順序容器 與前面類似 2.關聯容器 map和multimap 元素包含key 鍵 和值 value 兩部分 按照鍵對元素排序 map不允許重複元素出現,但multimap可以 set和multliset 是包含已排序物件的關聯容器 只是單純的鍵的集合 set不允許重複鍵出...