版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kzn2683331518/article/details/81301257
题目描述:https://www.luogu.org/problemnew/show/P1440
一个含有n项的数列(n<=2000000),求出每一项前的m个数到它这个区间内的最小值。若前面的数不足m项则从第1个数开始,若前面没有数则输出0。
输入样例#1: 复制
6 2 7 8 1 4 3 2
输出样例#1: 复制
0 7 7 1 1 3
题目分析:
从前m个数开始,遍历一个下标范围不超过m的单调递增队列,这个队列的第一个元素就是这个区间的最小值,其次分别是第二小,第三小。。。。
每次区间后移加入新元素,如果加入该元素不能继续维持队列的单调递增,那么要把当前队尾删去,直到该元素可以加入为止。
然后检查队首元素是否在该区间内,如果不在就要出队。
代码:
//#include <bits/stdc++.h>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
inline int read(){//读入整数
int k = 0, f = 1; char c = getchar();
while (c<'0' || c>'9')c == '-' && (f = -1), c = getchar();
while ('0' <= c&&c <= '9')k = k * 10 + c - '0', c = getchar();
return k*f;
}
int a[2000006], n;
//递增单调队列模板,维护区间长度不超过m的最小值
pair<int,int> que[2000006];//first:值 second:下标
int l,r,m;//头指针,尾指针,维护区间长度,入队数 = r-l+1;
//清空队列
inline void qclear(){l=1,r=0;}
//加入新元素,有效区间长度为m
void qpush(int x, int idx){
while(r>=l && x<=que[r].first)r--;//如需维护最大值,将此处<=改为>=即可
que[++r]=make_pair(x,idx);
while(que[l].second<=idx-m)l++;
}
//返回当前区间最大值
inline int qmax(){return que[l].first; }
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read();
qclear();
puts("0");
for(int i=1;i<n;i++){
qpush(a[i], i);
printf("%d\n",qmax());
}
return 0;
}