zoukankan      html  css  js  c++  java
  • 单调队列和单调栈

    所谓单调,就是容器中的数据是递增或递减的。

    单调队列

     单调队列中数据要么是递增的,要么是递减的。
    对于递减的单调队列,每次队尾加入一个数据,就把前面比它大的数从队尾弹出,然后再将本数据加入队列。

    比如对于队列1,3,4,6,9,如果插入5,
    就先比较5,9因为9>5,则9弹出队列,
    再比较6,5,6>5,则6出队,
    这时队列为1,3,4,比较4,5,4<5,则5入队

    有时对于滑动窗口的题,单调队列还要存储它的加入顺序(可以证明这个数据是单调递增的)。
    如果队首位置(当前队列中最早加入的数据)已经不属于滑动窗口,就将他从队首弹出。
    比如对于二元组队列(1,1),(3,2),(4,3),(6,4),(9,5)。
    注:第二个数据是加入队列的顺序,如果窗口长度是5,再加入(5,6);
    队尾的变化同上,队列变为(1,1),(3,2),(4,3),(5,6);
    这时最晚加入的数据和最早加入的跨度6已经大于窗口长度5,则队首数据(1,1)出队。

    结构体代码(单调递减队列)

    #include<cstdio>
    #define maxk 2000001//maxk为滑动窗口最长长度 
    struct HumdrumQueue{
        int s,t,k,a[maxk],id[maxk];//a为存储数据,id为入队顺序,s,t分别为队首,队尾+1,k为滑动窗口长度 
        int top(){//返回队首 
            if(s==t)return 0;//为空就返回0 
            return a[s];
        }
        void pop(){//队首出队 
            if(s!=t)s++;
        }
        void insert(int x,int i){//加入x,当前是第i个数据 
            while(s!=t&&a[t-1]>=x){//队尾不满足单调的出队 
                t--;
                if(t==-1)t=k;
            }
            if(i-id[s]>=k)pop();//队首如果不属于滑动窗口,则出队 
            a[t]=x,id[t++]=i,t%=maxk;//因为队列中元素不大于maxk,所以使用循环队列 
        }
    }q;
    int main(){
        return 0;
    } 

    例题

    求m区间内的最小值

    几乎是模板题

    #include<cstdio>
    #define maxk 2000001//maxk为滑动窗口最长长度 
    struct HumdrumQueue{
        int s,t,k,a[maxk],id[maxk];//a为存储数据,id为入队顺序,s,t分别为队首,队尾+1,k为滑动窗口长度 
        int top(){//返回队首 
            if(s==t)return 0;//为空就返回0 
            return a[s];
        }
        void pop(){//队首出队 
            if(s!=t)s++;
        }
        void insert(int x,int i){//加入x,当前是第i个数据 
            while(s!=t&&a[t-1]>=x){//队尾不满足单调的出队 
                t--;
                if(t==-1)t=k;
            }
            if(i-id[s]>=k)pop();//队首如果不属于滑动窗口,则出队 
            a[t]=x,id[t++]=i,t%=maxk;//因为队列中元素不大于maxk,所以使用循环队列 
        }
    }q;
    int main(){
        int n,m,x;scanf("%d%d",&n,&m);
        q.k=m;
        for(int i=0;i<n;i++){
            scanf("%d",&x);
            printf("%d
    ",q.top());
            q.insert(x,i);
        }
        return 0;
    }

    单调栈

    单调栈和单调队列差不多,分单调递增栈和单调递减栈,区别就是单调栈只能从栈顶弹出元素

    • 单调递增栈,则从栈顶到栈底的元素是严格递增的
    • 单调递减栈,则从栈顶到栈底的元素是严格递减的
    #include<cstdio>
    #define maxn 1000005
    struct MonotonicStack {//单调递增栈 
        int a[maxn],top;
        MonotonicStack(){
            top=0;
        }
        void pop(){//栈顶弹出 
            if(top)top--;
        }
        int size(){//返回站内元素个数 
            return top;
        }
        void insert(int x){//插入x 
            while(top&&a[top]<=x)top--;//将不满足单调的弹出 
            a[++top]=x;
        }
    }S;
    int main(){
        return 0;    
    }

    例题

    POJ Bad Hair Day

    #include<cstdio>
    #define maxn 1000005
    struct MonotonicStack {//单调递增栈 
        int a[maxn],top;
        MonotonicStack(){
            top=0;
        }
        void pop(){//栈顶弹出 
            if(top)top--;
        }
        int size(){//返回站内元素个数 
            return top;
        }
        void insert(int x){//插入x 
            while(top&&a[top]<=x)top--;//将不满足单调的弹出 
            a[++top]=x;
        }
    }S;
    long long sum; 
    int main(){
        int n,x;scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%d",&x);
            S.insert(x);
            sum+=S.size()-1;
        }
        printf("%lld",sum);
        return 0;    
    }
  • 相关阅读:
    2011 ACM-ICPC 成都赛区解题报告(转)
    Subarray Sorting (线段树)
    sample
    gamma correction / /alpha blend
    mipmap
    antialiasing
    汇编指令
    zfighting 的问题
    勉励自己
    Ambient Occulution
  • 原文地址:https://www.cnblogs.com/bennettz/p/7608796.html
Copyright © 2011-2022 走看看