zoukankan      html  css  js  c++  java
  • poj 2823 Sliding Window 单调队列

    poj 2823 Sliding Window
    //poj 2823  Sliding Window
    
    //单调队列
    
    //以下是复制别人的思路的,自己写的代码过不了,这代码也是模仿别人的
    
    //这题还可以用单调队列进行求解。开两个队列,一个维护最大值,
    //一个维护最小值。下面叙述最大队列,最小队列的方法类似。 
    
    //最大队列保证队列中各个元素大小单调递减(注意,不是单调不上升),
    //同时每个元素的下标单调递增。这样便保证队首元素最大,而且更新的
    //时候队首永远是当前最大。因此,这个队列需要在两头都可以进行删除,
    //在队尾插入。
    
    //维护方法:在每次插入的时候,先判断队尾元素,如果不比待插入元素
    //大就删除,不断删除队尾直到队尾元素大于待插入元素或者队空。删除
    //的时候,判断队首,如果队首元素下标小于当前段左边界就删除,不断
    //删除队首直到队首元素下标大于等于当前段左边界(注意:这时队列肯
    //定不为空),队首元素就是当前段的最优解。
    
    
    
    #include <stdio.h>
    #include <string.h>
    
    #define N 1000005
    
    int input()
    {
        char ch;
        int sign = 1, num = 0;
        while(ch = getchar(), ch == '\n' || ch == ' ');
    
        if(ch == EOF)
            return EOF;
    
        if(ch == '-')
        {
            sign = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            num = num * 10 + ch - '0';
            ch = getchar();
        }
        return sign * num;
    }
    
    int arr[N], mn[N], mx[N], time[N], ans[N];
    int len, k;
    
    void getMin()
    {
        int head = 1, tail = 0;
        for(int i = 1; i <= len; ++i)
        {       //删除队尾比要插入的数大的数
            while(head <= tail && mn[tail] >= arr[i])
                tail--;
            mn[++tail] = arr[i];    //把要插入的数插入到队尾,因此
            time[tail] = i;         //队列后面的数肯定比前面的数晚过期
            if(i >= k)
            {
                while(time[head] <= i - k)//注意:这里要等,eg:当i=k+1时
                    head++;               //第一个就过期了
                ans[i-k] = mn[head];
            }
        }
    }
    
    void getMax()
    {
        int head = 1, tail = 0;
        for(int i = 1; i <= len; ++i)
        {
            while(head <= tail && mx[tail] <= arr[i])
                tail--;
            mx[++tail] = arr[i];
            time[tail] = i;
            if(i >= k)
            {
                while(time[head] <= i - k)
                    head++;
                ans[i-k] = mx[head];
            }
        }
    }
    
    void print()
    {
        int end = len-k;    //总的有 1+end 组 宽度为 k 的数
        for(int i = 0; i <= end; ++i)
        {
            printf("%d", ans[i]);
            if(i != end)
                putchar(' ');
        }
        puts("");
    }
    
    int main()
    {
        while(scanf("%d%d", &len, &k) != EOF)
        {
            for(int i = 1; i <= len; ++i)
                arr[i] = input();
            getMin();
            print();
            getMax();
            print();
        }
        return 0;
    }
  • 相关阅读:
    图形化编程娱乐于教,Kittenblock实例,跟随鼠标指针画画的小螃蟹
    图形化编程娱乐于教,Kittenblock实例,图章效果的音乐画面
    图形化编程娱乐于教,Kittenblock实例,测试声音的响度
    图形化编程娱乐于教,Kittenblock实例,为背景添加音乐
    图形化编程娱乐于教,Kittenblock实例,小猫移动效果,碰触边缘反弹,左右翻转
    图形化编程娱乐于教,Kittenblock实例,按键控制角色发声
    Kittenblock实例,马赛克特效
    图形化编程娱乐于教,Kittenblock实例,广播消息
    redis的基本使用记录
    nginx学习笔记
  • 原文地址:https://www.cnblogs.com/gabo/p/2512158.html
Copyright © 2011-2022 走看看