hdu 3530 Subsequence 單調佇列

2021-08-04 06:28:21 字數 1055 閱讀 6467

題目鏈結

題意:給定陣列,求得最長的區間,使得其中最大值與最小值的差值在給定的範圍內(>=m, <=k)

思路:維護兩個佇列記錄元素下標,lo 與 hi (具體如何維護之後再講)

保證 a[lo] 單調增,且記當前處理到下標 i 的位置,則 a[lo[x]] 即為 lo[x-1]+1 ~ i 區間中的最小值

保證 a[hi] 單調增,且記當前處理到下標 i 的位置,則 a[hi[x]] 即為 lo[x-1]+1 ~ i 區間中的最大值

顯見,兩個隊頭對應a中元素的差值即為 一直到 i 的這段區間內的最大值與最小值的差,

如果這個差值 > k, 則將兩個隊頭中最早的乙個出隊(為了保證區間最長),直到差值滿足 <= k,

注意到,如果差值 < m, 則暫時不需要處理,因為隨著區間變長,最大值與最小值的差距只會增加,不會減小,

至於入隊,

以 lo 陣列為例,將 i 入隊時,考慮 a[i] 是否大於隊尾,如果大於直接入隊,否則從隊尾開始向前踢元素,直到隊尾 <= a[i], 然後再將 i 入隊,

顯然這樣就能滿足上述要求

ac**如下:

#include #include #define maxn 100010

using namespace std;

int a[maxn], n, m, k, hi[maxn], lo[maxn];

void work()

if (a[hi[s2]] - a[lo[s1]] >= m && a[hi[s2]] - a[lo[s1]] <= k) len = max(len, i - l + 1);

// for (int j = s1; j < t1; ++j) printf("%d ", a[lo[j]]); printf("\n");

// for (int j = s2; j < t2; ++j) printf("%d ", a[hi[j]]); printf("\n");

}printf("%d\n", len);

}int main()

hdu 3530 單調佇列

單調佇列就是佇列中的元素是單調遞增或遞減的。比如把 5 2 3 1 4 入隊 減 增 5 5 5 2 2 5 3 2 3 5 3 1 1 5 4 1 4 這個還是好理解的,但是,我們得會用單調佇列這一特性去解決題目,抽象出題目中有類似的操作。subsequence 題意 給三個數 n,x,y 接下來...

hdu3530 Subsequence 單調佇列

題目 在乙個序列中找乙個最長子串,使得子串的m 極差 k.維護乙個遞減的單調佇列q1 隊首為當前最大 同時維護乙個遞增的單調佇列q2 隊首為當前最小 控制最大減最小 小於等於k 若最大減最小大於等於m,則更新答案。include include include include includeusin...

hdu 3530(單調佇列)

傳送門 題解 用乙個單調不公升的佇列維護最大值,乙個單調不減的佇列維護最小值。如果不滿足條件,後移答案區間左端點,取兩個佇列頭指標的元素較小的乙個 位置盡量靠前使區間盡量長 include include include include using namespace std const int m...