nkoj 2152
description
給你乙個長度為n(n<=10^6)的陣列,乙個長為k的滑動的窗體從最左移至最右端,你只能見到視窗的k個數,每次窗體向右移動一位,找出窗體所包含的數字的最大和最小值,如下表所示: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 -3 5 [3 6 7] 3 7
input
第1行為n,k,第2行為長度為n的陣列。
output
共2行,第1行是每個位置的min value,第2行是每個位置的max value。
sample input
8 31 3 -1 -3 5 3 6 7
sample output
-1 -3 -3 -3 3 33 3 5 5 6 7
分析:對區域最大值而言:如果出現遞增的情況,例如 1,5......那麼1比5先出隊,只要有5在,1就不是最大值,1,就可以刪掉,形成乙個單調遞減的佇列。
對最小值也同樣成立,只不過形成的是單調遞增序列
每一次取隊首即可。
**如下:
#includeusing namespace std;
const int maxn=1000006;
inline void _read(int &x)
for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
if(!sign)x=-x;
}struct _int;
_int qmax[maxn],qmin[maxn];
// qmax保持單調遞減,qmin保持單調遞增
int ans_min[maxn],ans_max[maxn];
int main();
} for(i=k+1;i<=n;i++); //當前元素入隊
//qmin的操作與qmax相同
while(minhead!=mintail&&qmin[mintail-1].num>x)mintail--;
while(minhead!=mintail&&i-qmin[minhead].pos>=k)minhead++;
qmin[mintail++]=(_int);
} ans_max[++cur]=qmax[maxhead].num; //最後再取一次;
ans_min[cur]=qmin[minhead].num;
for(i=1;i<=cur;i++)printf("%d ",ans_min[i]);
printf("\n");
for(i=1;i<=cur;i++)printf("%d ",ans_max[i]);
}
滑動視窗 單調佇列
給定乙個大小為n 106的陣列。有乙個大小為k的滑動視窗,它從陣列的最左邊移動到最右邊。您只能在視窗中看到k個數字。每次滑動視窗向右移動乙個位置。以下是乙個例子 該陣列為 1 3 1 3 5 3 6 7 k為3。視窗位置 最小值 最大值 1 3 1 3 5 3 6 7 1 3 1 3 1 3 5 3...
單調佇列 滑動視窗
p1886 滑動視窗 模板 單調佇列 有乙個長為 n 的序列 a,以及乙個大小為 k 的視窗。現在這個從左邊開始向右滑動,每次滑動乙個單位,求出每次滑動後視窗中的最大值和最小值。如果按照暴力方法做的話,每一次判斷相鄰的k個數的最大值和最小值,複雜度為o n k 肯定會超時,因此就想到把每次的最大值和...
滑動視窗 單調佇列
單調佇列與普通佇列不一樣的地方就在於單調佇列既可以從隊首出隊,也可以從隊尾出隊。那麼我們應該怎樣實現單調佇列呢?就拿樣例來談談,設以最小的為標準。8 3 1 3 1 3 5 3 6 7 下文中我們用q來表示單調佇列,p來表示其所對應的在原列表裡的序號。1.由於此時隊中沒有乙個元素,我們直接令1進隊。...