http://poj.org/problem?id=2823
题意:给出n个数,窗口大小为k,窗口从1滑到n-k,问所以窗口内的最大最小值;
解法:单调队列存两个数据一个是值,一个是值的的下标。两个指针(首尾指针),单调增队列求最小值,每次询问队首元素下标是否超出
窗口范围,超出则队首指针向后移(剔除队首),然后队首值就是该窗口的最小值。
最大值同理。
//#include<bits/stdc++.h> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <string> #include <stdio.h> #include <queue> #include <stack> #include <map> #include <set> #include <string.h> #include <vector> #define ME(x , y) memset(x , y , sizeof(x)) #define SC scanf #define rep(i , j , n) for(int i = j ; i <= n ; i++) #define red(i , n , j) for(int i = n ; i >= j ; i--) #define INF 0x3f3f3f3f #define mod 1000000007 #define PI acos(-1) #define pii pair<int,int> #define fi first #define se second using namespace std; typedef long long ll ; const int maxn = 1e6+10; int a[maxn] ; int val[maxn] ; pair<int , int>que[maxn]; int main() { int n , k ; cin >> n >> k; rep(i , 1 , n){ scanf("%d" , &a[i]); } int front = 1 , rear = 0 , len = 0 ; rep(i , 1 , n){ while(rear >= front && que[rear].fi >= a[i]){ rear--; } if(rear >= front && i - que[front].se + 1 > k){ front++; } que[++rear].fi = a[i]; que[rear].se = i ; if(i >= k){ val[++len] = que[front].fi ; } } rep(i , 1 , len){ cout << val[i] << " " ; } cout << endl; front = 1 , rear = 0 , len = 0 ; rep(i , 1 , n){ while(rear >= front && que[rear].fi <= a[i]) rear--; if(rear >= front && i - que[front].se + 1 > k){ front++; } que[++rear].fi = a[i] ; que[rear].se = i ; if(i >= k){ val[++len] = que[front].fi; } } rep(i , 1 , len){ cout << val[i] << " " ; } cout << endl; return 0; }