滑动窗口
现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。例如:The array is [1 3 -1 -3 5 3 6 7], and k = 3.
窗口 最小值 最大值
[1 3 -1] -3 5 3 6 7 -1 3
1 [3 -1 -3]5 3 6 7 -3 3
1 3 [-1 -3 5] 3 6 7 -3 5
1 3 -1 [-3 5 3] 6 7 -3 5
1 3 -1 -3[5 3 6] 7 3 6
1 3 -1 -35 [3 6 7] 3 7
输入格式
输入一共有两行,第一行为n,k。第二行为n个数(<INT_MAX).
输出格式
输出共两行,第一行为每次窗口滑动的最小值第二行为每次窗口滑动的最大值
样例输入
8 31 3 -1 -3 5 3 6 7
样例输出
-1 -3 -3 -3 3 33 3 5 5 6 7
注释
现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。例如:The array is [1 3 -1 -3 5 3 6 7], and k = 3.
窗口 最小值 最大值
[1 3 -1] -3 5 3 6 7 -1 3
1 [3 -1 -3]5 3 6 7 -3 3
1 3 [-1 -3 5] 3 6 7 -3 5
1 3 -1 [-3 5 3] 6 7 -3 5
1 3 -1 -3[5 3 6] 7 3 6
1 3 -1 -35 [3 6 7] 3 7
输入格式
输入一共有两行,第一行为n,k。第二行为n个数(<INT_MAX).
输出格式
输出共两行,第一行为每次窗口滑动的最小值第二行为每次窗口滑动的最大值
样例输入
8 31 3 -1 -3 5 3 6 7
样例输出
-1 -3 -3 -3 3 33 3 5 5 6 7
注释
50%的数据,n<=10^5100%的数据,n<=10^6
这是典型的给定队列长度,在O(n)内求区间[l,r]中的最大或最小值问题。
设队列b[],用来存值的下标(方便判断队列中的数是否在区间内)
现在求最大值
1.元素入队前,如果该数大于队列中它前面的数(j>i,a[j]>a[i])那么前面的数不会是最大值,也没有意义,因此删去。(同时该操作保证了队列中元素的单调性)
2.介于单调性,用二分优化:在队列b[head]~b[tail]中找到最后一个a[i]<a[b[k]],那么i值直接插到k+1处,即tail=k+1
3.判断当前队头在不在所求区间中,若不在,出队
while b[head]<i-k+1 do head:=head+1;
4.当前区间的最大值即为队头a[b[head]]
最小值类似
var n,i,k,head,tail,j,k1:longint;
a,b:array[1..1000000]of longint;
f:array[1..1000000]of longint;
<span style="color:#3333ff;">function check(l,r,x:longint):longint;//二分
var mid:longint;
begin
repeat
mid:=(l+r) div 2;
if x>a[b[mid]] then
l:=mid+1
else
r:=mid-1;
until l>r;
check:=l;
end;</span>
function check1(l,r,x:longint):longint;
var mid:longint;
begin
repeat
mid:=(l+r) div 2;
if x>a[b[mid]] then
r:=mid-1
else
l:=mid+1;
until l>r;
check1:=l;
end;
begin
read(n,k);
for i:=1 to n do read(a[i]);
f[1]:=a[1];
head:=1;tail:=1;
b[1]:=1;
<span style="color:#3333ff;">for i:=2 to n do <span style="font-family: Arial, Helvetica, sans-serif;">//最小值</span>
begin
k1:=check(head,tail,a[i]);
tail:=k1;
b[tail]:=i;
while b[head]<i-k+1 do head:=head+1;
f[i]:=a[b[head]];
end;</span>
for i:=k to n do if i<n then write(f[i],' ') else writeln(f[i]);
head:=1;tail:=1;
b[1]:=1;
for i:=2 to n do //最大值
begin
k1:=check1(head,tail,a[i]);
tail:=k1;
b[tail]:=i;
while b[head]<i-k+1 do head:=head+1;
f[i]:=a[b[head]];
end;
for i:=k to n do if i<n then write(f[i],' ') else writeln(f[i]);
end.