• POJ 2328 (单调队列)


    题目输出一个n,一个k,分别代表n个数,长度为k的框,求狂每移动一次,框里面的最大值最小值

    样例

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

    最小

    -1 -3 -3 -3 3 3

    最大

    3 3 5 5 6 7
    暴力复杂度高,这里用单调队列

    最小值 (单调递增的队列)
    1 这个队列可以可以尾巴和头都去数。
    2 当尾巴的数大于要存进来的数时候,尾巴弹出
    3 当队列头的数和尾巴的数之间的距离大于等于k,头的数弹出
    (这题cin cout可能会超时)
      每次队列中的数字是这样变化的
    • 1
    • 1 3 //3大于1,存入
    • -1  //-1小于3,3弹出。 -1小于1,1弹出
    • -3
    • -3 5
    • -3 3
    • 3 6 //-3 与 6 的距离大于k-1,-3弹出
    • 3 6 7

    输出 队列头 就行

    最大值  是单调递增区别不大
    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <map>
    #include <iomanip>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <set>
    #include <vector>
    
    #define ll long long
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    
    #define MAX INT_MAX
    #define FOR(i,a,b) for( int i = a;i <= b;++i)
    #define bug cout<<"--------------"<<endl
    using namespace std;
    struct node    //模拟的队列,place记录下标,nub记录数
    {
        int place,nub;
    }que[1100000];
    int v[1100000];
    int n,k;
    void findmin()
    {
        memset(que,0,sizeof(que));
        int head=1,tail=0;
        for(int i=1;i<=k-1;++i) // 先把前k-1个数预处理进去队列中
        {
            while(que[tail].nub>=v[i] && tail>=head)
            {
                tail--;
            }
            tail++;
            que[tail].nub=v[i];
            que[tail].place=i;
        }
        for(int i=k;i<=n;++i)
        {
            while(que[tail].nub>=v[i] && tail>=head)
            {
                tail--;
            }
            tail++;
            que[tail].nub=v[i];
            que[tail].place=i;
            while(que[tail].place-que[head].place>=k)
            {
                head++;
            }
            printf("%d ",que[head].nub);
        }
    }
    void findmax()
    {
        memset(que,0,sizeof(que));
        int head=1,tail=0;
        for(int i=1;i<=k-1;++i)
        {
            while(que[tail].nub<=v[i] && tail>=head)
            {
                tail--;
            }
            tail++;
            que[tail].nub=v[i];
            que[tail].place=i;
        }
        for(int i=k;i<=n;++i)
        {
            while(que[tail].nub<=v[i] && tail>=head)
            {
                tail--;
            }
            tail++;
            que[tail].nub=v[i];
            que[tail].place=i;
            while(que[tail].place-que[head].place>=k)
            {
                head++;
            }
            printf("%d ",que[head].nub);
        }
    }
    int main()
    {
    
        cin>>n>>k;
        FOR(i,1,n)
        {
            cin>>v[i];
        }
        findmin();
        printf("
    ");
        findmax();
    
    }



  • 相关阅读:
    图片api
    基于NoneBot的天气查询插件
    在Linux云服务上运行酷Q机器人并DIY自己的功能
    破解zip密码的几种方法
    攻防世界wp--crypto 幂数加密
    攻防世界wp--crypto Caesar
    攻防世界wp--web command_execution
    攻防世界wp--web weak_auth
    python中yield的用法以及和yield from的区别
    Linux进阶之正则,shell三剑客(grep,awk,sed),cut,sort,uniq
  • 原文地址:https://www.cnblogs.com/jrfr/p/11250699.html
Copyright © 2020-2023  润新知