滑动窗口
给一个长度为N的数组,一个长为K的滑动窗体从最左端移至最右端,你只能看到窗口中的K个数,每次窗体向右移动一位你的任务是找出窗体在各个位置时的最大值和最小值。
链接:https://ac.nowcoder.com/acm/problem/50528
来源:牛客网
单调队列,以单调递增为例:使用双端队列,若堆头元素不在窗口内则弹出队头,若队尾元素小于当前元素则弹出队尾,最后将当前元素插入队尾。队头元素就是最大值。
这个题时间空间卡的都很死。
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int res[1000010],cnt=0;
struct Num{
public:
int value;
int location;
};
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n, k, t;
cin >> n >> k;
deque<Num> big(1000010), small(1000010);
for(int i = 0;i < n; i++){
cin >> t;
while(!big.empty() && ((i - big.front().location + 1) > k))big.pop_front();
while(!big.empty() && big.back().value < t)big.pop_back();
while(!small.empty() && ((i - small.front().location + 1) > k))small.pop_front();
while(!small.empty() && small.back().value > t)small.pop_back();
big.push_back({t, i});
small.push_back({t, i});
if(i >= k - 1){
res[cnt++] = (big.front().value);
cout << small.front().value;
if(i != n - 1){
cout << " ";
}
}
}
cout << endl;
for(int i = 0;i < cnt;i++){
cout << res[i];
if(i != cnt - 1)cout << " ";
}
cout << endl;
}