单调队列的题目
滑动窗口
https://ac.nowcoder.com/acm/problem/50528
- 单调队列问题
a[l],a[l + 1],a[l + 2]....a[r-2],a[r-1],a[r],当这个区间往右移动的时候,只会a[l]离开窗口,a[r + 1]进入窗口,那么我们只需比较这个即可
典型单调队列题目,我们队列左端存的是当前最优解,当窗口往右移动时,我们看这个队列左端是不是已经不再 k 这个范围内了,如果是的话我们让他出队,然后我们看 a[i] 也就是当前新加的元素 ,如果他比队列中的某些元素小的话,那么他就可能成为后面的最优解,那么我们往前找到一个合适的位置来存储他,也就是他前面的元素都比他小,后面的元素都比他大。 - 注意队列中存的是他的下标 l = r = 1 开始 ,让第一个元素先进队 注意是 ++ r
#include<bits/stdc++.h> #define pr printf #define sc scanf #define fur(i,a,b) for(int i = a; i<= b ;i++) #define fdr(i,a,b) for(int i = a; i>= b ;i--) using namespace std; const int N = 1e6 + 5; int du[N],n ,k ,a[N]; typedef long long ll; int main() { // freopen("in.txt","r",stdin); sc("%d %d",&n ,&k); int l = 1 ,r = 1; for(int i = 1 ; i <= n ; i ++){ sc("%d",&a[i]); } du[l] = 1; if(k ==1)pr("%d ",a[1]); for(int i = 2 ; i <= n ;i ++){ if(i - du[l] >= k && l <= r)l++; while(l <= r && a[du[r ]] >=a[i]) r--; du[++r] = i; // ++ r 是因为他要在队尾插入 if(i>=k)pr("%d ",a[du[l]]); } puts(""); l = 1, r= 1; du[l] = 1; if(k ==1)pr("%d ",a[1]); for(int i = 2 ; i <= n ;i ++){ if(i - du[l] >= k && l <= r)l++; while(l <= r && a[du[r ]] <=a[i]) r--; du[++r] = i; if(i>=k)pr("%d ",a[du[l]]); } puts(""); return 0; }