coding使我忘记化学
如题,实质上是在考察单调队列,最大值和最小值可分别用一个单调队列排序输出。
操作方便,定义两个数组分别储存队列和每个元素的序号
由题得队列原则:队列数组中末尾元素的序号与开头元素序号之差不能大于k,使队列的范围保持为窗口的宽度
在保证这点之后,只要同时保证队列始终是单调排序,这样当元素序号>=窗口宽度(保证窗口圈满元素)时,只要循环输出开头元素就可以了。
那么如何保证队列单调?拿最大值举例:在向队列中添加元素的过程中,如果一个队列中元素X后的元素Y数值更大,那么X将失去成为最大值的可能性,故需被移出队列。
以上即为本题队列操作方法,最小值同理。
完整代码如下:
#include<iostream> #include<cstdio> using namespace std; const int maxn=1000001; int item[maxn],line[maxn],element[maxn];//item存放序号,line为单调数列 int main() { int n,k,first,last; cin>>n>>k; for(int i=1;i<=n;i++) cin>>element[i];//读入 first=1; last=0; for(int i=1;i<=n;++i)//排序输出最小值 { while(first<=last&&line[last]>=element[i]) last--; line[++last]=element[i]; item[last]=i; while(item[first]<=i-k) first++; if(i>=k) cout<<line[first]<<" "; } cout<<" "; first=1; last=0;//两个单调队列间过渡的细节不能忘记 for(int i=1;i<=n;++i)//排序输出最大值 { while(first<=last&&line[last]<=element[i]) last--; line[++last]=element[i]; item[last]=i; while(item[first]<=i-k) first++; if(i>=k) cout<<line[first]<<" "; } return 0; }