• 【t019】window(单调队列)


    Time Limit: 2 second
    Memory Limit: 256 MB

    【问题描述】

    给你一个长度为N 的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表:
    

    Window position Min value Max value
    [1 3 -1] -3 5 3 6 7 -1 3
    1 [3 -1 -3] 5 3 6 7 -3 3
    1 3 [-1 -3 5] 3 6 7 -3 5
    1 3 -1 [-3 5 3] 6 7 -3 5
    1 3 -1 -3 [5 3 6] 7 3 6
    1 3 -1 -3 5 [3 6 7] 3 7

    你的任务是找出窗口在各位置时的Max value和Min value。
    

    【输入格式】

    第一行N,K,第二行为长度为N的数组
    

    【输出格式】

    第一行每个位置的Min value,第二行每个位置的Max value
    

    【输入样例1】

    8 3
    
    1 3 -1 -3 5 3 6 7
    

    【输出样例1】

    -1 -3 -3 -3 3 3
    
    3 3 5 5 6 7
    

    数据规模

    20%:N≤500;50%:N≤100000;100%:N≤1000000;
    

    【题目链接】:http://noi.qz5z.com/viewtask.asp?id=t019

    【题解】

    最小值维护一个单调递增队列就能搞定;(a[i]<=a[i+1]
    每次加入队列中的元素先和队尾比较一下,对于队尾比它大的数,直接删掉就好,因为要求的是最小值,而你加入的这个数是在框框里面的,那么如果你比这个数还大,那么你肯定没有存在的价值了;
    然后对于队头元素,如果它不在框框里面也全都删掉,直到队头元素在框框里为止,然后输出队头元素;
    最大值类似.
    (可以在2s内出)

    【完整代码】

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    const int MAXN = 1e6+100;
    
    int n,k,a[MAXN];
    int m[MAXN],mm[MAXN],h,t;
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        scanf("%d%d",&n,&k);
        for (int i = 1;i <= n;i++)
            scanf("%d",&a[i]);
        h = 1,t = 0;
        for (int i = 1;i <= k-1;i++)
        {
            while (t>=h && m[t]>=a[i]) t--;
            t++;
            m[t] = a[i];mm[t] = i;
        }
        for (int i = k;i<= n;i++)
        {
            while (t>=h && m[t]>=a[i]) t--;
            t++;
            m[t] = a[i];mm[t] = i;
            while (mm[h]<i-k+1 && h <= t) h++;
            printf("%d",m[h]);
            if (i==n)
                puts("");
            else
                putchar(' ');
        }
        h = 1,t = 0;
        for (int i = 1;i <= k-1;i++)
        {
            while (t>=h && m[t]<=a[i]) t--;
            t++;
            m[t] = a[i];mm[t] = i;
        }
        for (int i = k;i <= n;i++)
        {
            while (t>=h && m[t]<=a[i]) t--;
            t++;
            m[t] = a[i];mm[t] = i;
            while (mm[h]<i-k+1 && h <= t) h++;
            printf("%d",m[h]);
            if (i==n)
                puts("");
            else
                putchar(' ');
        }
        return 0;
    }
  • 相关阅读:
    关于ios8斯坦福公开课第二课
    关于cocoapods和swift中使用oc第三方
    swift 关于闭包和函数
    同步、异步请求
    AFNETWORKING tabelView没有reloadData,报错unsupported URL
    在模型中获取网络数据,刷新tableView
    界面随键盘顶起来
    Java并发编程:线程池的使用
    比较好的介绍线程池的文章
    一篇很不错的dubbo学习文章
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626667.html
Copyright © 2020-2023  润新知