zoukankan      html  css  js  c++  java
  • POJ 2823 Sliding Window(单调队列 || 线段树)题解

    题意:求每个长度为k的数组的最大值和最小值

    思路:

    1.用线段树创建维护最大值和最小值,遍历询问,简单复习了一下...有点手生

    2.单调队列:

    可以看一下详解

    单调队列顾名思义就是一个单调递增或者递减的队列,我们可以通过队列瞬间得到当前队列的最大值和最小值。以查找当前区间最小值为例,我们需要维护一个递增的队列,那么当前队列队首就是最小值。在维护队列的过程中要注意:

    1、如果队列的长度一定,要判断队首元素是否在规定范围内,如果超范围则队首移动,直到在范围内为止。

    2、每次加入元素时和队尾比较,如果队尾元素大于要插入的元素且队列非空,则队尾元素依次出队,直到满足队列的单调性为止,这是为了保证队列的单调性。

    线段树:

    #include<cstdio>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N = 1e6+5;
    int n,k,Max[N<<2],Min[N<<2],ansMa[N],ansMi[N],cnt;
    void build(int l,int r,int rt){
        if(l == r){
            int a;
            scanf("%d",&a);
            Max[rt] = Min[rt] = a;
            return;
        }
        int m = (l + r) / 2;
        build(l,m,rt<<1);
        build(m+1,r,rt<<1|1);
        Max[rt] = max(Max[rt<<1],Max[rt<<1|1]);
        Min[rt] = min(Min[rt<<1],Min[rt<<1|1]);
    }
    int queryMa(int L,int R,int l,int r,int rt){
        if(l == r) return Max[rt];
        if(L <= l && R >= r){
            return Max[rt];
        }
        int m = (l + r) / 2;
        int MAX = -1e8;
        if(L <= m) MAX = max(MAX,queryMa(L,R,l,m,rt<<1));
        if(R > m) MAX = max(MAX,queryMa(L,R,m+1,r,rt<<1|1));
        return MAX;
    }
    int queryMi(int L,int R,int l,int r,int rt){
        if(l == r) return Min[rt];
        if(L <= l && R >= r){
            return Min[rt];
        }
        int m = (l + r) / 2;
        int MIN = 1e8;
        if(L <= m) MIN = min(MIN,queryMi(L,R,l,m,rt<<1));
        if(R > m) MIN = min(MIN,queryMi(L,R,m+1,r,rt<<1|1));
        return MIN;
    }
    int main(){
        while(~scanf("%d%d",&n,&k)){
            build(1,n,1);
            for(int i = 1,j = k;i <= n-k+1;i++,j++){
                ansMa[i] = queryMa(i,j,1,n,1);
                ansMi[i] = queryMi(i,j,1,n,1);
            }
            for(int i = 1;i <= n-k+1;i++){
                printf("%d ",ansMi[i]);
            }
            printf("
    ");
            for(int i = 1;i <= n-k+1;i++){
                printf("%d ",ansMa[i]);
            }
            printf("
    ");
        }
        return 0;
    }
    

    单调队列:

    #include<cstdio>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N = 1e6+5;
    int a[N],q[N],pos[N],n,k;
    int MAX[N],MIN[N];
    void get_max(){ //单调递减队列
        int head,tail;
        head = tail = 0;    //tail指向队尾(空)
        for(int i = 1;i < k;i++){
            while(head < tail && q[tail - 1] <= a[i])   //保证递减
                tail--;
            q[tail] = a[i];
            pos[tail++] = i;  //记录个数的位置,为后续查找q[head]是否超出范围准备
        }
        for(int i = k;i <= n;i++){
            while(head < tail && q[tail - 1] <= a[i])
                tail--;
            q[tail] = a[i];
            pos[tail++] = i;
            while(head < tail && pos[head] < i-k+1)
                head++;
            MAX[i-k] = q[head];
        }
        for(int i = 0;i < n-k+1;i++) printf("%d ",MAX[i]);
        printf("
    ");
    }
    void get_min(){ ////单调递增队列
        int head,tail;
        head = tail = 0;
        for(int i = 1;i < k;i++){
            while(head < tail && q[tail - 1] >= a[i])  //保证递增
                tail--;
            q[tail] = a[i];
            pos[tail++] = i;
        }
        for(int i = k;i <= n;i++){
            while(head < tail && q[tail - 1] >= a[i])
                tail--;
            q[tail] = a[i];
            pos[tail++] = i;
            while(head < tail && pos[head] < i-k+1)
                head++;
            MIN[i-k] = q[head];
        }
        for(int i = 0;i < n-k+1;i++) printf("%d ",MIN[i]);
        printf("
    ");
    }
    int main(){
        while(~scanf("%d%d",&n,&k)){
           for(int i = 1;i <= n;i++) scanf("%d",&a[i]);
           get_min();
           get_max();
        }
        return 0;
    }
    


  • 相关阅读:
    字符串替换
    Problem E: Automatic Editing
    正则表达式学习(1)
    python中的enumerate使用
    使用bottle进行web开发(9):文件上传;json传递
    使用bottle进行web开发(8):get的参数传递,form里的额数据传递等
    dict的setdefault(学习bottle源代码)
    使用bottle进行web开发(6):Response 对象
    使用bottle进行web开发(5):Generating Content
    使用bottle进行web开发(4):HTTPError
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9408795.html
Copyright © 2011-2022 走看看