P1886 【模板】单调队列 / 滑动窗口(洛谷题面)
题目
题目描述:
有一个长为 n 的序列 a,以及一个大小为 k 的窗口。现在这个窗口从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最小值和最大值。
例如,对于序列 [1,3,−1,−3,5,3,6,7] 以及 k=3,有如下过程:
窗口位置[1 3 -1] -3 5 3 6 7 1 [3 -1 -3] 5 3 6 7 1 3 [-1 -3 5] 3 6 7 1 3 -1 [-3 5 3] 6 7 1 3 -1 -3 [5 3 6] 7 1 3 -1 -3 5 [3 6 7]最小值−1−3−3−333最大值335567
输入格式:
输入一共有两行,第一行有两个正整数 n,k;
第二行有 n 个整数,表示序列 a。
输出格式:
输出共两行,第一行为每次窗口滑动的最小值;
第二行为每次窗口滑动的最大值。
数据范围与说明:
【数据范围】
对于 50% 的数据,1≤n≤105;
对于 100% 的数据,1≤k≤n≤106,ai∈[−231,231)。
输入输出样例 #1
输入:
输出:
1 2
| -1 -3 -3 -3 3 3 3 3 5 5 6 7
|
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include<bits/stdc++.h> using namespace std; int n,k; deque<int>q; int a[1000005]; int main(){ cin>>n>>k; for(int i=0;i<n;i++){ cin>>a[i]; } for(int i=0;i<n;i++){ if(!q.empty()&&q.front()<=i-k){ q.pop_front(); } while(!q.empty()&&a[q.back()]>=a[i]){ q.pop_back(); } q.push_back(i); if(i>=k-1){ cout<<a[q.front()]<<" "; } } cout<<endl; q.clear(); for(int i=0;i<n;i++){ if(!q.empty()&&q.front()<=i-k){ q.pop_front(); } while(!q.empty()&&a[q.back()]<=a[i]){ q.pop_back(); } q.push_back(i); if(i>=k-1){ cout<<a[q.front()]<<" "; } } return 0; }
|