Time Limit: 12000MS | Memory Limit: 65536K | |
Total Submissions: 52179 | Accepted: 14945 | |
Case Time Limit: 5000MS |
Description
Window position | Minimum value | Maximum value |
---|---|---|
[1 3 -1] -3 5 3 6 7 | -1 | 3 |
1 [3 -1 -3] 5 3 6 7 | -3 | 3 |
1 3 [-1 -3 5] 3 6 7 | -3 | 5 |
1 3 -1 [-3 5 3] 6 7 | -3 | 5 |
1 3 -1 -3 [5 3 6] 7 | 3 | 6 |
1 3 -1 -3 5 [3 6 7] | 3 | 7 |
Your task is to determine the maximum and minimum values in the sliding window at each position.
Input
Output
Sample Input
8 3 1 3 -1 -3 5 3 6 7
Sample Output
-1 -3 -3 -3 3 3 3 3 5 5 6 7
Source
题意:求窗口大小为k的最值
题解:之前这一题早就做过了,用的是线段树,准备使用RMQ,但是发现爆了空间了,最近又遇到了一个二维的RMQ,无论是线段树还是RMQ都会MLE,这里要使用一个神奇的算法啦:单调队列,之前早就有了解过,可是感觉学了一些数据结构好像用处并不明显,这里在极端情况下,单调队列就体现出优势了,他的空间,时间复杂度都是O(N),可以维护区间的RMQ
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<string> #include<bitset> #include<utility> #include<functional> #include<iomanip> #include<sstream> #include<ctime> using namespace std; #define N int(1e6+10) #define inf int(0x3f3f3f3f) #define mod int(1e9+7) typedef long long LL; int a[N],deq[N],mx[N]; int n, k; void out(int s,int t) { for (int i = s; i <t; i++) printf("%d ", a[deq[i]]); puts("-------------------------------"); } void solve() { int s = 0, t = 0; for (int i = 0; i < n; i++) { while (s < t&&a[deq[t - 1]] >= a[i])t--; deq[t++] = i; if (i - k + 1 >= 0) { mx[i - k + 1] = a[deq[s]]; //out(s, t); if (deq[s] == i - k + 1)s++; } } for (int i = 0; i <= n - k; i++) printf("%d%c", mx[i], i == n - k ? '\n' : ' '); } void solve1() { int s = 0, t = 0; for (int i = 0; i < n; i++) { while (s < t&&a[deq[t - 1]] <= a[i])t--; deq[t++] = i; if (i - k + 1 >= 0) { //out(s, t); mx[i - k + 1] = a[deq[s]]; if (deq[s] == i - k + 1)s++; } } for (int i = 0; i <= n - k; i++) printf("%d%c", mx[i], i == n - k ? '\n' : ' '); } int main() { #ifdef CDZSC freopen("i.txt", "r", stdin); //freopen("o.txt","w",stdout); int _time_jc = clock(); #endif while (~scanf("%d%d", &n, &k)) { for (int i = 0; i < n; i++)scanf("%d", &a[i]); solve(); solve1(); } return 0; } /* 1 3 1 -1 -3 5 -3 3 -3 6 3 -3 7 6 3 */