• 【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('
    ');
        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;
    }

     

  • 相关阅读:
    单调栈问题解析
    Linux进程状态切换
    Shell编程小例子
    Linux之shell编程
    树的遍历框架
    你真的会求1-100有多少个素数吗
    java实现LRU算法
    从上到下打印二叉树 III
    从上到下打印二叉树I
    模拟盘电路板调试过程中出现的问题
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7253480.html
Copyright © 2020-2023  润新知