先用暴力:
for从k-1(大于板长)点循环
for 上级点往前找最小
分析:
如果i < j,a[ i ] > a[ j ],那么a[ i ]就一定不会用上,
即:前点>后点,那么前点就一定用不上 ,因为:后点的存在时间比前点长 && 不满足后点就一定不满足前点,所以构造递增序列即可
由题意,1.每次返回窗口内最小的值,所以是窗口(队列)内队头值 2.窗口有长度,所以使用队列控制长度
#include <iostream> using namespace std; const int N=1000005; int n,k,q[N],a[N]; int hh,tt; int main() { cin>>n>>k; hh=0, tt=-1; //因为有长度限制所以是队列 for(int i=0;i<n;i++){ scanf("%d",&a[i]); if(q[hh]+k-1<i) hh++;//头+板长<尾(现点) ,队头的点已经在窗口外 while(hh<=tt&&a[q[tt]]>=a[i]) tt--;//队列不空且要加的点小于队尾(构建递增数组), q[++tt]=i;//满足递增后压入 if(i>=k-1)printf("%d ",a[q[hh]]);//现点>板长+0(起始)窗口完全在数组内,防止之前部分窗口不在数组 } printf("\n"); hh=0, tt=-1;//不要忘记初始化 for(int i=0;i<n;i++){ if(q[hh]+k-1<i) hh++; while(hh<=tt&&a[q[tt]]<=a[i]) tt--;//改成< q[++tt]=i; if(i>=k-1)printf("%d ",a[q[hh]]); } printf("\n"); return 0; }