NC50528
题意
给你一个长度为n的数组,依次求长度为k的区间中的最小值,最大值为多少。
思路
单调队列(双端队列) 时间复杂度
单调队列性质:
- 队列中的元素其对应在原来的列表中的顺序必须是单调递增的。
- 队列中元素的大小必须是单调递*(增/减/甚至是自定义也可以
求最小值的做法:维护一个单调队列,头部元素的下标为,尾部元素的后一位下标为,其中的值为(存数组中的下标)使得中的元素满足且即下标递增下标所对应的值也是有序的(可自定义)。
最大值对应只是改变了对应值有序的排列方式。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int>P; const double eps = 1e-8; const int NINF = 0xc0c0c0c0; const int INF = 0x3f3f3f3f; const ll mod = 1e9 + 7; const ll maxn = 1e6 + 5; int n,k,a[maxn],q[maxn],x[maxn],y[maxn]; void solve1(){ int s=1,t=1; for(int i=1;i<=n;i++){ while(s<t&&a[i]<=a[q[t-1]]) t--;//维护单调队列的单调性 q[t++]=i; if(i>=k){ x[i]=a[q[s]]; } if(q[s]==i-k+1) s++;//不在滑动窗口范围内弹出 } } void solve2(){ int s=1,t=1; for(int i=1;i<=n;i++){ while(s<t&&a[i]>=a[q[t-1]]) t--; q[t++]=i; if(i>=k){ y[i]=a[q[s]]; } if(q[s]==i-k+1) s++; } } void print(){ for(int i=k;i<n;i++){ cout<<x[i]<<" "; } cout<<x[n]<<'\n'; for(int i=k;i<n;i++){ cout<<y[i]<<" "; } cout<<y[n]<<'\n'; } int main(){ ios::sync_with_stdio(false); cin.tie(0); cin>>n>>k; for(int i=1;i<=n;i++){ cin>>a[i]; } solve1(); solve2(); print(); return 0; }