HDU 3415單調佇列

2021-06-18 23:50:32 字數 1616 閱讀 4984

這個題目屬於常見題型,給定一組環狀數列,求出其中長度不超過k的數字之和的最大值。。

用到了字首和的技巧,比如要求i,j間所有數字之和,可以提前在輸入的時候計算出從0~i的數字之和及從0~j的數字之和,那麼sum[i~j]=sum[j]-sum[i];

現在的問題是求出最大的sum[i~j].那麼我們可以固定sum[j]的值,當sum[i]最小時,整個式子值最大。。顯然會用到單調遞增佇列,不斷維護進隊出隊操作即可,

保持單調遞增佇列的單調性不被破壞,則隊頭元素始終是最小的值;

至於sum[j]不斷列舉就行了,至此問題得到完美解決。

下面是我的**,調了半天才發現乙個極其sb的錯誤,維護進隊操作時,應該用sum[q[tail]]和sum[cur]比較進行刪除隊尾元素的操作,我不知道為何手賤的寫成了sum[q[head]]......t_t,地球人已經阻止不了我犯二的腳步了~~qaq

/******************************

* author :crazy_石頭

* data structure: 單調佇列

* created time:2013/112/31 23:27

* pro:hdoj 3415

* judge status:accepted

* memory:2098k

* time:171ms

* ps:可以優化輸入輸出加速,orz

* 這題也很基礎,不過多了起始點和結束點的維護罷了;

*******************************/

#include

#include

#include

#include

usingnamespacestd;

#define rep(i,h,m) for(int i=(h);i<=(m);i++)

#define inf

0x3fffffff

const

int maxn=100000+5;

int sum[maxn<<1],q[maxn<<1],a[maxn<<1];//q儲存下標,元素的值可以通過訪問下標間接訪問到;

int res,test;

int head,tail,n,k;

int start,end;

inlinevoid enqueue(int cur)//維護單調遞增隊列入隊過程;

inlinevoid dequeue(int cur)//不斷維護該操作即可;

}int main()

rep(i,n+1,n+k)

sum[i]=sum[i-1]+a[i-n];//處理迴圈數列的方法:在其後面複製一串數字;

enqueue(0);

rep(i,1,n+k)

printf("%d %d %d\n",res,start>n?start-n:start,end>n?end-n:end);

}return0;}

* this source code was highlighted byycdoit

. ( style: fog )

HDU3415單調佇列

這題是單調佇列的典型運用。至於單調佇列,就是乙個雙端佇列,在隊首 f 出隊,在隊尾 b 出隊入隊,我們要維護整個佇列的元素是單調的,比如,我們要動態查詢從左向右的區間的最小值,那麼我們就要在佇列中維護乙個單調遞增的序列,從左向右列舉,佇列的元素還有乙個id值,代表這個元素在原序列中的位置,然後左邊的...

HDU3415單調佇列

這題是單調佇列的典型運用。至於單調佇列,就是乙個雙端佇列,在隊首 f 出隊,在隊尾 b 出隊入隊,我們要維護整個佇列的元素是單調的,比如,我們要動態查詢從左向右的區間的最小值,那麼我們就要在佇列中維護乙個單調遞增的序列,從左向右列舉,佇列的元素還有乙個id值,代表這個元素在原序列中的位置,然後左邊的...

HDU 3415 單調佇列

求長度不大於 k 的最大子段和 求字首和,列舉答案的右端點,對於每個右端點,求以該點為右端點,長度為 k 的區間的最小值 用單調佇列維護值單調遞增的下標,對於每個右端點,若隊首元素與當前位置的距離不滿足要求,則出隊,否則記錄答案 includeusing namespace std typedef ...