滑動視窗
關於這道題,首先會想到暴搜,但資料太大,絕對超時。用暴搜的思路來說,就是乙個乙個列舉,再在當中找出最大最小值,會發現,每次都在重複列舉,那有沒有什麼方法可以儲存之前的值?
這就引出主題了——單調佇列
單調佇列,就是乙個佇列,但有單調性,就是佇列裡的元素是遞增或遞減的
例如 1 2 3 4 5 6 7 8 9 就是乙個單調佇列,每個元素都比之前的大
那單調佇列與滑動視窗有什麼關係
首先要建立兩個雙向佇列,乙個求最大,乙個求最小,接下來就是主要思想
a[i].num表數值,a[i].id表位址,先把第乙個元素放進去,然後依次放入後面的元素,在放每個元素之前,得先做乙個維護
一. 保證隊頭為最大值
二. 保持單調性(就保持其遞增或遞減)
三. 位址小於視窗前端的不入隊
先遍歷一遍佇列,把位址小於視窗前端的pop掉
那先拿需要放入的元素與隊內元素比較,比它小的,pop出去,直到有元素比它大為止,若都比它小,就全踢完,每次迴圈過後輸出最大最小值,這樣就能保證每個元素都只會進隊出隊一次,時間複雜度就為o(n)。
結合**,理解一下
#include #include #include #define n 1000005
#define ll long long
using namespace std;
int n , k ;
ll maxn[n] , minn[n] ;
struct que a[n];
deque z;//求min
deque q;//求max
int main()
z.push_back(a[1]);
q.push_back(a[1]);
minn[1] = a[1].num;
maxn[1] = a[1].num;
for(int i = 2 ; i <= n ; i ++ )
printf("%lld",minn[k]);
for(int i = k + 1 ; i <= n ; i ++ )
printf(" %lld" , minn[i]);
putchar('\n');
printf("%lld",maxn[k]);
for(int i = k + 1; i <= n ; i ++ )
printf(" %lld", maxn[i]);
putchar('\n');
return 0;
}
本人也為萌新,歡迎一起交流討論 滑動視窗 單調佇列入門題
給定乙個大小為n 106n 106的陣列。有乙個大小為k的滑動視窗,它從陣列的最左邊移動到最右邊。您只能在視窗中看到k個數字。每次滑動視窗向右移動乙個位置。以下是乙個例子 該陣列為 1 3 1 3 5 3 6 7 k為3。視窗位置 最小值最大值 1 3 1 3 5 3 6 7 13 1 3 1 3 ...
滑動視窗 單調佇列入門題
給定乙個大小為n 106n 106的陣列。有乙個大小為k的滑動視窗,它從陣列的最左邊移動到最右邊。您只能在視窗中看到k個數字。每次滑動視窗向右移動乙個位置。以下是乙個例子 該陣列為 1 3 1 3 5 3 6 7 k為3。視窗位置 最小值最大值 1 3 1 3 5 3 6 7 13 1 3 1 3 ...
單調佇列 入門
今天寫了人生中第乙個單調佇列,激動ing 先看一道單調佇列的入門題 乙個含有n項的數列 n 2000000 求出每一項前面的第m個數到它這個區間內的最小值。先寫出動規方程 f i min j合法 很明顯的,這是乙個n 2的動規,但是,我們可以注意到,數列中有些數無論如何都不會被選到.如 1 2 8 ...