【Sliding Window】单调队列

题目描述

给你一个长度为 N 的数组,一个长为 K 的滑动的窗体从最左移至最右端,你只能见到窗口的 K 个整数,每次窗体向右移动一位,如下表: 

你的任务是找出窗口在各位置时的最大值和最小值。

输入格式

输入的第 1 行是两个整数 n,k,第 2 行为长度为 n 的数组(即有 n 个整数)。

输出格式

 输出 2 行,第 1 行是每个位置的最小值,第 2 行是每个位置的最大值。 

样例数据 1

输入  [复制]

8 3 
1 3 -1 -3 5 3 6 7

输出

-1 -3 -3 -3 3 3 
3 3 5 5 6 7

备注

【数据范围】 

对于 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;
}

 

posted @ 2017-07-29 08:54  CzYoL  阅读(196)  评论(0编辑  收藏  举报