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

    题意很明显,注意用C++提交,不然会超时。

    说说我对单调队列的理解吧。

    其实就是每次都在队头保留了ans。就是每次你想知道第i个位置的答案,每次取出队头元素就OK了。

    然后就是怎么维护了。

    例如要求最大值,那么,队头应该是一个最大值的。所以这个队列是单调递减的,每次插入a[i]的时候,维护它单调递减就OK,同时可以把它插入的这个位置后面的值删除了,是没用了。因为a[i]比他们大,而且比他们新。

    关键就是这个新了。

    应该这些元素不在这个窗口的话,那些就属于废弃元素,废弃元素不能被选择,所以队列有第二个参数。id。保留队头元素在数组a[i]的pos。那么当对头的id == i - k的时候。它就是废弃的了。然后把head++即可。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    int n,k;
    const int maxn = 1e6 + 20;
    int a[maxn];
    struct node {
        int val,id;
        node () {}
        node (int vv,int ii) : val(vv), id(ii) {}
    }que[maxn];
    int ans_min[maxn];
    int ans_max[maxn];
    void work ()
    {
        int lenmin = 0, lenmax = 0;
        scanf ("%d%d", &n, &k);
        for (int i = 1; i <= n; ++i) {
            scanf ("%d", a + i);
        }
    //    if (k > n) {
    //        while (1);
    //    }
        que[1].val = a[1];
        que[1].id = 1;
        int head = 1, tail = 1;
        for (int i = 2; i <= k; ++i) { //开始预处理
            while (tail >= head && a[i] >= que[tail].val) --tail;
            ++tail;
            que[tail].val = a[i];
            que[tail].id = i;
        }
        ans_max[++lenmax] = que[head].val;
        for (int i = k + 1; i <= n; ++i) {
            while (tail >= head && a[i] >= que[tail].val) --tail;
            ++tail;
            que[tail].val = a[i]; que[tail].id = i;
            while (head <= tail && que[head].id == i - k) ++head;
            ans_max[++lenmax] = que[head].val;
        }
    
        head = tail = 1;
        que[tail].val = a[1];
        que[tail].id = 1;
        for (int i = 2; i <= k; ++i) {
            while (tail >= head && a[i] <= que[tail].val) --tail;
            ++tail;
            que[tail].val = a[i];
            que[tail].id = i;
        }
        ans_min[++lenmin] = que[head].val;
        for (int i = k + 1; i <= n; ++i) {
           while (tail >= head && a[i] <= que[tail].val) --tail;
           ++tail;
           que[tail].val = a[i]; que[tail].id = i;
           while (head <= tail && que[head].id == i - k) ++head;
           ans_min[++lenmin] = que[head].val; //每次取队头就是ans
        }
        for (int i = 1; i <= lenmin; ++i) {
            printf ("%d ", ans_min[i]);
        }
        printf ("
    ");
        for (int i = 1; i <= lenmax; ++i) {
            printf ("%d ", ans_max[i]);
        }
        printf ("
    ");
        return ;
    }
    
    int main()
    {
    #ifdef local
        freopen("data.txt","r",stdin);
    #endif
        work ();
        return 0;
    }
    View Code
  • 相关阅读:
    springboot上传文件并检查图片大小与格式
    java判断传进来的是否是图片
    Spring boot设置文件上传大小限制
    Mybatis 中遍历map 参数中的 list 和 array 属性
    更优雅地关闭资源
    解决springboot druid 数据库批量更新错误问题
    EditPlus行首行尾批量添加字符 以及其它常用正则
    mybatis传入List实现批量更新的坑
    【libreoffice】libreoffice实现office转pdf、html、jpg等格式数据
    【tomcat】sessionId学习(未完待续)
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/5819448.html
Copyright © 2011-2022 走看看