单调队列

单调队列它分两种,一种是单调递增的,另外一种是单调递减的。不断地向缓存数组里读入元素,也不时地去掉最老的元素,不定期的询问当前缓存数组里的最小的元素和最大的元素。用单调队列来解决问题,一般都是需要得到当前的某个范围内的最小值或最大值。

一道经典的板子题

题意:k表示缓存数组的大小,在每k个数中询问最小值与最大值。

题解:最小值做法是,用数组模拟单调队列(或者用deque),_index数组表示下标为i的元素在原数组中的位置,每次存进数组里的数,必须使得数组是严格单调递增的,也就是a[_index[right]] < a[i],否则,数组的尾部必须扔出元素,直到满足该条件为止,插入以后,还需判断数组长度与k的关系,由于当前状态数组已经是严格单调递增,所以只需判断i-_index[left]+1是否小于等于k即可。每次数组中的头部元素就是数组的最小值,由于每个元素只有进出,所以时间复杂度为O(N)。最大值做法类似。

PS:需要使用C++提交。

AC_CODE:

/*
 * Author: $%U%$
 * Time: $%Y%$-$%M%$-$%D%$ $%h%$:$%m%$:$%s%$
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define FOR(I, A, B) for (int I = (A); I <= (B); ++I)
#define FORS(I, S) for (int I = 0; S[I]; ++I)
#define RS(X) scanf("%s", (X))
#define SORT_UNIQUE(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
typedef long long ll,LL;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<PII> VPII;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;
#ifdef HOME
 #define DEBUG(...) {printf("# ");printf(__VA_ARGS__);puts("");}
#else
 #define DEBUG(...)
#endif
#define Test() int t; cin >> t; while(t--) 
#define in freopen("in.txt","r",stdin);
#define out freopen("out.txt","w",stdout);
#define mod 998244353
#define inf 1<<30
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
const int maxn = 1e6+5;
int a[maxn];
int _index[maxn];
int n,k;

void getMin(){
    int left(1),right(1);
    _index[left] = _index[right] = 1;
    FOR(i,1,k-1){
        while(left <= right && a[_index[right]] >= a[i]) right -= 1;
        _index[++right] = i;
    }
    FOR(i,k,n){
        while(left <= right && a[_index[right]] >= a[i]) right -= 1;
        _index[++right] = i;
        while(left <= right && _index[left] < i - k + 1) left += 1;
        printf("%d%c",a[_index[left]],(i==n?10:32));
    }
}

void getMax(){
    int left(1),right(1);
    _index[left] = _index[right] = 1;
    FOR(i,1,k-1){
        while(left <= right && a[_index[right]] <= a[i]) right -= 1;
        _index[++right] = i;
    }
    FOR(i,k,n){
        while(left <= right && a[_index[right]] <= a[i]) right -= 1;
        _index[++right] = i;
        while(left <= right && _index[left] < i - k + 1) left += 1;
        printf("%d%c",a[_index[left]],(i==n?10:32));
    }
}

int main(){
    while(scanf("%d%d",&n,&k) != EOF){
    FOR(i,1,n) scanf("%d",&a[i]);
    getMin();
    getMax();}
}

你可能感兴趣的:(单调队列)