模板
typedef long long ll;
const int maxn=;
int a[maxn],qmax[maxn],qmin[maxn],savemax[maxn],savemin[maxn];
int main(){
int n,k,cnt=1;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int beg=1,top=0;//beg为qmax的队列的头(**记住队列存的是数组下标**),top为qmax的尾(不包括头)
int st=1,ed=0;//beg为qmin的队列的头(**记住队列存的是数组下标**),top为qmin的尾(不包括头)
for(int i=1;i<=n;i++){
while(beg<=top&&a[i]>=a[qmax[top]]) top--;//保证队列中从头到尾的所映射的a[]是呈现递减形式(也就是说qmax存的是a[]下标)
qmax[++top]=i;
while(st<=ed&&a[i]<=a[qmin[ed]]) ed--;//保证队列中从头到尾的所映射的a[]是呈现递增形式(也就是说qmin存的是a[]下标)
qmin[++ed]=i;
if(i>=k){//i含义是窗口的最右端下标,所以当i>=k的时候,窗口已经形成。因此,可以选择最大值和最小值。
while(qmax[beg]<=i-k) beg++;//每个窗口的最左端都是一个确定值,所以要移动队列的头使得它的映射值(原数组下标)在窗口里面
while(qmin[st]<=i-k) st++;
savemax[cnt]=a[qmax[beg]];//save就是保存值
savemin[cnt]=a[qmin[st]];
cnt++;
}
}
return 0;
}
滑动窗口
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
给一个长度为N的数组,一个长为K的滑动窗体从最左端移至最右端,你只能看到窗口中的K个数,每次窗体向右移动一位,如下图:
你的任务是找出窗体在各个位置时的最大值和最小值。
输入描述:
第1行:两个整数N和K;
第2行:N个整数,表示数组的N个元素(≤2 \times10^9≤2×10
9
);
输出描述:
第一行为滑动窗口从左向右移动到每个位置时的最小值,每个数之间用一个空格分开;
第二行为滑动窗口从左向右移动到每个位置时的最大值,每个数之间用一个空格分开。
示例1
输入
复制
8 3
1 3 -1 -3 5 3 6 7
输出
复制
-1 -3 -3 -3 3 3
3 3 5 5 6 7
备注:
对于20 %20%的数据,K≤N≤1000;
对于50 %50%的数据,K≤N≤10^5K≤N≤10
5
;
对于100 %100%的数据,K≤N≤10^6K≤N≤10
6
。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=2e6+5;
int a[maxn],qmax[maxn],qmin[maxn];
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int beg=1,top=0;
int st=1,ed=0;
for(int i=1;i<=n;i++)
{
while(st<=ed&&a[i]<=a[qmin[ed]])
ed--;
qmin[++ed]=i;
if(i>=k)
{
while(qmin[st]<=i-k)st++;
printf("%d ",a[qmin[st]]);
}
}
cout<<endl;
for(int i=1;i<=n;i++)
{
while(beg<=top&&a[i]>=a[qmax[top]])
top--;
qmax[++top]=i;
if(i>=k)
{
while(qmax[beg]<=i-k) beg++;
printf("%d ",a[qmax[beg]]);
}
}
cout<<endl;
return 0;
}