題目鏈結
題意:給定陣列,求得最長的區間,使得其中最大值與最小值的差值在給定的範圍內(>=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...