给你一个长度为 N 的数组,一个长为 K 的滑动的窗体从最左移至最右端,
你只能见到窗口的K个数,每次窗体向右移动一位,如下表:
你的任务是找出窗口在各位置时的 max value,min value.
INPUT:
第 1 行 n,k,
20%:n<=500;
50%: n<=100000;
100%: n<=1000000;
第 2 行为长度为 n 的数组
8 3
1 3 -1 -3 5 3 6 7
OUTPUT:
2 行,
第 1 行每个位置的 min value,
第 2 行每个位置的 max value
-1 -3 -3 -3 3 3
3 3 5 5 6 7
题解:
如果每次都要sort的话,小数据可以O(n*k),但是数据大的话一定会超时。
那么该如何搞呢? 单调队列。O(n)效率很高!!
单调队列,一个元素单调的队列,可以保证队头是最小(最大)的;
可以通过队首删除,队尾插入来维护最优值。
这道题,就是通过单调队列来维护一个最大值和最小值。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<string> 6 #include<algorithm> 7 #include<queue> 8 #include<cstdlib> 9 #include<iomanip> 10 #include<ctime> 11 using namespace std; 12 const int maxn=5000001; 13 int n,k; 14 int a[maxn],q[maxn]; 15 int tail=0,head=0; 16 17 int main() 18 { 19 cin>>n>>k; 20 for(int i=1;i<=n;i++) 21 cin>>a[i]; 22 q[tail]=1; 23 for(int i=2;i<k;i++) 24 { 25 while(a[i]<a[q[tail]]&&tail>=head) 26 { 27 tail--; 28 } 29 q[++tail]=i; 30 } 31 for(int i=k;i<=n;i++) 32 { 33 if(i-q[head]==k) head++; 34 while(a[i]<a[q[tail]]&&tail>=head) 35 { 36 tail--; 37 } 38 q[++tail]=i; 39 cout<<a[q[head]]<<" "; 40 } 41 cout<<endl; 42 memset(q,0,sizeof(q)); 43 head=0,tail=0; 44 q[tail]=1; 45 for(int i=2;i<k;i++) 46 { 47 while(a[i]>a[q[tail]]&&tail>=head) 48 { 49 tail--; 50 } 51 q[++tail]=i; 52 } 53 for(int i=k;i<=n;i++) 54 { 55 if(i-q[head]==k) head++; 56 while(a[i]>a[q[tail]]&&tail>=head) 57 { 58 tail--; 59 } 60 q[++tail]=i; 61 cout<<a[q[head]]<<" "; 62 } 63 cout<<endl; 64 return 0; 65 }