算法复习——单调队列(sliding windows,ssoi)
题目:
题目描述
给你一个长度为 N 的数组,一个长为 K 的滑动的窗体从最左移至最右端,你只能见到窗口的 K 个整数,每次窗体向右移动一位,如下表:
你的任务是找出窗口在各位置时的最大值和最小值。
输入格式
输入的第 1 行是两个整数 n,k,第 2 行为长度为 n 的数组(即有 n 个整数)。
输出格式
输出 2 行,第 1 行是每个位置的最小值,第 2 行是每个位置的最大值。
样例数据 1
备注
【数据范围】
对于 20% 的数据:n<=500;
对于 50% 的数据:n<=100000;
对于 100% 的数据:n<=1000000;
题解:
单调队列模板
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<cstring> #include<string> #include<algorithm> using namespace std; const int N=1e6+5; int n,k,num[N],que[N],tail,head; inline int R() { int i=1,f=0; char c; for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar()); if(c=='-') { i=-1; c=getchar(); } for(;c<='9'&&c>='0';c=getchar()) f=(f<<3)+(f<<1)+c-'0'; return f*i; } int main() { //freopen("window.in","r",stdin); n=R(); k=R(); for(int i=1;i<=n;i++) num[i]=R(); head=1,tail=0; for(int i=1;i<=n;i++) { while(head<=tail&&i-que[head]>=k) head++; while(num[i]<=num[que[tail]]&&head<=tail) tail--; que[++tail]=i; if(i>=k) cout<<num[que[head]]<<" "; } cout<<endl; head=1,tail=0; for(int i=1;i<=n;i++) { while(head<=tail&&i-que[head]>=k) head++; while(head<=tail&&num[i]>=num[que[tail]]) tail--; que[++tail]=i; if(i>=k) cout<<num[que[head]]<<" "; } return 0; }