現在有一堆數字共n個數字(n<=10^6),以及乙個大小為k的視窗。現在這個從左邊開始向右滑動,每次滑動乙個單位,求出每次滑動後視窗中的最大值和最小值。
例如:the array is [1 3 -1 -3 5 3 6 7], and k = 3.
輸入一共有兩行,第一行為n,k。
第二行為n個數(小於int_max).
輸出共兩行,第一行為每次視窗滑動的最小值
第二行為每次視窗滑動的最大值
輸入樣例#1:
8 31 3 -1 -3 5 3 6 7
輸出樣例#1:
-1 -3 -3 -3 3 3
3 3 5 5 6 7
50%的資料,n<=10^5
100%的資料,n<=10^6
解釋一下題意:給出乙個長度為n的序列,以及乙個滑動視窗的長度k.要求出每一次移動後當前位置滑動視窗上的最大值和最小值.
看這個資料範圍,用資料結構什麼的是很難過的,很可能被卡常或者是爆空間什麼的.所以這裡提供了一種神奇的做法:
我們來模擬一下樣例的序列(求滑動視窗最大值):1 3 -1 -3 5 3 6 7.
* 首先是1入隊.
* 然後3入隊判斷,3比1大,而1又在3前面,所以1比3會先出隊,意味著1在有生之年是當不成最大值了,所以1可以出隊了.此時最大值是隊首3.
* 接著-1入隊判斷.-1比3小,說明如果3出隊了-1還是有可能成為最大值的.所以-1直接入隊.最大值仍是隊首3.
* -3入隊判斷,比-1小,仍有可能成為最大值,先入隊.此時最大值依舊是隊首3.
* 5入隊判斷,比隊尾大,說明之前入隊的-3,-1,3都不可能成為最大值了.於是把它們都出隊.把5入隊,此時最大值是隊首5.
* 3入隊同理.
* 6入隊,彈出3,5.最大值是6.
* 7入隊,彈出6,最大值是7.
那麼我們大概就得出了優先佇列的維護方法:
* 每個元素入隊前判斷它之前的元素是否可能成為最值.將不可能成為最值的元素都彈出隊.
* 將該元素入隊.
* 統計當前狀態下佇列的元素個數,從隊首開始彈出一定數量元素保證佇列中元素個數在滑動視窗大小內.
* 此時隊首的值就是維護的最值.
具體在操作過程中可以用兩個陣列模擬佇列,乙個記錄元素的值來判斷是否可能成為最值.另乙個記錄元素下標來判斷當前佇列元素個數.
下面看一下**注釋:
#includeusing namespace std;
const int n=1000000+5;
const int inf=2147483647;
int n, k, w[n];
int q1[n], q2[n];//q1統計元素的值,q2統計下標.
int gi()
while(i>='0'&&i<='9')
return ans * f;
}int main()
printf("\n"); h = 1; t = 0;//
for(int i=1;i<=n;i++)
printf("\n");
return 0;
}
洛谷 P1886 滑動視窗
洛谷 p1886 滑動視窗 單調佇列 單調遞增佇列 使得每個入隊元素都小於已有元素 保持遞增 遇到隊尾元素小於未入隊元素時,彈出隊尾再使未入隊元素入隊 資料結構 deque,因為滑動視窗需要判斷佇列元素是否過時,而deque可以通過pop front 彈出隊首元素 每次滑動都記錄隊首元素即可。inc...
洛谷p1886 滑動視窗
滑動視窗 單調佇列經典題,話說我第一次做這個題的時候是用線段樹水的 兩個單調佇列分別維護最小最大值,因為視窗有k的長度限制所以維護下標更方便 又由於是從左往右掃過去的,所以可以保證下標和值都是單調的 讀乙個維護乙個,以單增佇列為例,每讀入乙個元素就把前面比它大的都彈出,然後將元素入隊 因為視窗有k長...
洛谷P1886 滑動視窗
題目描述輸入格式 輸入一共有兩行,第一行為n,k。第二行為n個數 輸出格式 輸出共兩行,第一行為每次視窗滑動的最小值 第二行為每次視窗滑動的最大值 輸入輸出樣例 輸入 1 8 31 3 1 3 5 3 6 7 輸出 1 1 3 3 3 3 3 3 3 5 5 6 7 說明 提示 50 的資料,n 1...