zoukankan      html  css  js  c++  java
  • POJ 2823 Sliding Window

    题意:滑窗问题。一个长度为n的序列,分别求前k个数中的最值,第2个到第k + 1个数中的最值,...,直到最后一个元素。

    解法:单调队列。对于求最小值来说,题中的样例k为3,序列为为

                     1 3 -1 -3 5 3 6 7

    每次放入数字前,检查队头的编号,看是否已经超过了滑窗的范围,如果超过了弹出队头;还要看队尾元素是否比将要放入的数字大,因为新放入的数字如果比较小那么之前放入的大的数字肯定不可能是答案了,所以要弹出。这两个操作完成后再放入新插入的元素。此时队头元素即为当前滑窗的答案。

    样例解释为:

    队列              答案

    1                      -

    1  3                  -

    -1                    -1

    -3                    -3

    -3 5                 -3

    -3 3                 -3

    3 6                   3

    3 6 7                3

    代码:

    用了双端队列……勉强水过……用数组模拟更快……然而我比较懒……嗯哼

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<math.h>
    #include<limits.h>
    #include<time.h>
    #include<stdlib.h>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #include<deque>
    #define LL long long
    using namespace std;
    const int MAXN = 1000005;
    struct node
    {
        int v, pos;
        node(int v, int pos) : v(v), pos(pos) {}
        node() {}
    }num[MAXN];
    int ans1[MAXN], ans2[MAXN];
    deque <node> maxn, minn;
    int main()
    {
        int n, k;
        while(~scanf("%d%d", &n, &k))
        {
            for(int i = 0; i < n; i++)
            {
                scanf("%d", &num[i].v);
                num[i].pos = i;
            }
            int ans = 0;
            for(int i = 0; i < n; i++)
            {
                if(!minn.empty() && minn.front().pos <= i - k)
                    minn.pop_front();
                while(!minn.empty() && minn.back().v >= num[i].v)
                    minn.pop_back();
                minn.push_back(num[i]);
                if(i >= k - 1)
                {
                    ans = minn.front().v;
                    ans1[i - k + 1] = ans;
                }
                while(!maxn.empty() && maxn.back().v <= num[i].v)
                    maxn.pop_back();
                if(!maxn.empty() && maxn.front().pos <= i - k)
                    maxn.pop_front();
                maxn.push_back(num[i]);
                if(i >= k - 1)
                {
                    ans = maxn.front().v;
                    ans2[i - k + 1] = ans;
                }
            }
            for(int i = 0; i < n - k + 1; i++)
            {
                if(i)
                    printf(" ");
                printf("%d", ans1[i]);
            }
            puts("");
            while(!minn.empty())
                minn.pop_back();
            for(int i = 0; i < n - k + 1; i++)
            {
                if(i)
                    printf(" ");
                printf("%d", ans2[i]);
            }
            puts("");
            while(!maxn.empty())
                maxn.pop_back();
        }
        return 0;
    }
    

      

  • 相关阅读:
    一个简易的词法分析器
    Wireshark的简单使用
    TCP的三次握手和四次挥手详解
    在WEB显示实时视频流
    linux 下 查看进程的启动时间和运行时间
    mac os x 安装adb
    C++ 和 java 使用 AES CBC 128 加解密
    转:Java中String与byte[]的转换
    对称加密
    Google C++ Style Guide在C++11普及后的变化
  • 原文地址:https://www.cnblogs.com/Apro/p/4568801.html
Copyright © 2011-2022 走看看