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;
    }
  • 相关阅读:
    EIGRP-16-其他和高级的EIGRP特性-2-非等价负载分担
    EIGRP-15-其他和高级的EIGRP特性-1-路由器ID
    EIGRP-14-EIGRP的命名模式
    EIGRP-13-弥散更新算法-停滞在活动状态
    EIGRP-12-弥散更新算法-DUAL的FSM(*没写完)
    EIGRP-11-弥散更新算法-EIGRP中的本地计算和弥散计算
    EIGRP-10-弥散更新算法-计算距离,报告距离,可行距离和可行性条件
    EIGRP-9-弥散更新算法-拓扑表
    EIGRP-8-路由器的邻接关系
    EIGRP-7-可靠传输协议
  • 原文地址:https://www.cnblogs.com/gabo/p/2512158.html
Copyright © 2011-2022 走看看