【Sliding Window】单调队列
题目描述
给你一个长度为 N 的数组,一个长为 K 的滑动的窗体从最左移至最右端,你只能见到窗口的 K 个整数,每次窗体向右移动一位,如下表:
你的任务是找出窗口在各位置时的最大值和最小值。
输入格式
输入的第 1 行是两个整数 n,k,第 2 行为长度为 n 的数组(即有 n 个整数)。
输出格式
输出 2 行,第 1 行是每个位置的最小值,第 2 行是每个位置的最大值。
样例数据 1
备注
【数据范围】
对于 20% 的数据:n<=500;
对于 50% 的数据:n<=100000;
对于 100% 的数据:n<=1000000;
题目分析
入门级别单调队列。分别维护一个单调递增和单调递减的队列,每次添加新数并维护单调性,然后删除队首的在区间外面的数,最后队首就是答案。
code
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> using namespace std; const int N = 1000005, oo = 0x3f3f3f3f; typedef pair<int, int> P; int data[N], head, tail, n, k; P que[N]; inline int read(){ int i = 0, f = 1; char ch = getchar(); for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar()); if(ch == '-') f = -1, ch = getchar(); for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0'); return i * f; } inline void wr(int x){ if(x < 0) putchar('-'), x = -x; if(x > 9) wr(x / 10); putchar(x % 10 + '0'); } int main(){ n = read(), k = read(); for(int i = 1 ; i <= n; i++) data[i] = read(); tail = head = 1; que[head].second = oo; for(int i = 1; i <= n; i++){ if(data[i] < que[head].second) que[head = tail = 1] = P(i, data[i]); else{ while(head < tail && que[tail].second > data[i]) tail--; que[++tail] = P(i, data[i]); } while(que[head].first <= i - k) head++; if(i >= k) wr(que[head].second), putchar(' '); // cout<<endl<<"!!";for(int j = head; j <= tail; j++) cout<<"("<<que[j].first<<") "<<que[j].second<<" ";cout<<endl; } putchar('\n'); tail = head = 1; que[head].second = -oo; for(int i = 1; i <= n; i++){ if(data[i] > que[head].second) que[head = tail = 1] = P(i, data[i]); else{ while(head < tail && que[tail].second < data[i]) tail--; que[++tail] = P(i, data[i]); } while(que[head].first <= i - k) head++; if(i >= k) wr(que[head].second), putchar(' '); // cout<<endl<<"!!";for(int j = head; j <= tail; j++) cout<<que[j].first<<" "<<que[j].second<<" ";cout<<endl; } return 0; }