首页 > 其他分享 >【数据结构】单调队列专题(滑动窗口问题)

【数据结构】单调队列专题(滑动窗口问题)

时间:2023-05-06 18:11:53浏览次数:49  
标签:min 队列 tt ++ int hh 滑动 数据结构 row

一维滑动窗口

154. 滑动窗口

下标从0开始,数组模拟队列

#include <iostream>

using namespace std;

const int N = 1e6 + 10;

int n, k;
int a[N], q[N];

int main()
{
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);

    int hh = 0, tt = -1;
    for (int i = 0; i < n; i ++ )
    {
        if (hh <= tt && i - k + 1 > q[hh]) hh ++ ;
        while (hh <= tt && a[q[tt]] >= a[i]) tt -- ;
        q[++ tt] = i;
        if (i >= k - 1) printf("%d ", a[q[hh]]);
    }
    puts("");
    hh = 0, tt = -1;
    for (int i = 0; i < n; i ++ )
    {
        if (hh <= tt && i - k + 1 > q[hh]) hh ++ ;
        while (hh <= tt && a[q[tt]] <= a[i]) tt -- ;
        q[++ tt] = i;
        if (i >= k - 1) printf("%d ", a[q[hh]]);
    }
    return 0;
}

作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/1161854/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

下标从0开始,STL队列

#include <iostream>
#include <deque>

using namespace std;

const int N = 1e6 + 10;

int n, k;
int a[N];

int main()
{
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
    deque<int> q;
    for (int i = 0; i < n; i ++ )
    {
        if (q.size() && i - (k - 1) > q.front()) q.pop_front();
        while (q.size() && a[q.back()] >= a[i]) q.pop_back();
        q.push_back(i);
        if (i >= k - 1) printf("%d ", a[q.front()]);  // 注:输出的是队头元素
    }
    printf("\n");
    q = deque<int>();
    for (int i = 0; i < n; i ++ )
    {
        if (q.size() && i - (k - 1) > q.front()) q.pop_front();
        while (q.size() && a[q.back()] <= a[i]) q.pop_back();
        q.push_back(i);
        if (i >= k - 1) printf("%d ", a[q.front()]); // 注:输出的是队头元素
    }
    return 0;
}

作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/1161854/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

下标从1开始,数组模拟队列

#include <iostream>

using namespace std;

const int N = 1e6 + 10;

int n, k;
int q[N], a[N];

int main()
{
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);

    int hh = 0, tt = -1;
    for (int i = 1; i <= n; i ++ )
    {
        if (hh <= tt && i - k >= q[hh]) hh ++ ; // 也可写成i - k + 1 > q[hh]
        while (hh <= tt && a[q[tt]] >= a[i]) tt -- ;
        q[++ tt] = i;
        if (i >= k) printf("%d ", a[q[hh]]);
    }
    puts("");
    hh = 0, tt = -1;
    for (int i = 1; i <= n; i ++ )
    {
        if (hh <= tt && i - k >= q[hh]) hh ++ ; // 也可写成i - k + 1 > q[hh]
        while (hh <= tt && a[q[tt]] <= a[i]) tt -- ;
        q[++ tt] = i;
        if (i >= k) printf("%d ", a[q[hh]]);
    }
    return 0;
}

作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/1161854/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

二维滑动窗口

1091. 理想的正方形

#include <iostream>

using namespace std;

const int N = 1010;

int n, m, k;
int w[N][N], row_max[N][N], row_min[N][N];
int q[N];

void get_max(int a[], int b[], int tot)
{
    int hh = 0, tt = -1;
    for (int i = 0; i < tot; i ++ )
    {
        if (hh <= tt && i - k + 1 > q[hh]) hh ++ ;
        while (hh <= tt && a[q[tt]] <= a[i]) tt -- ;
        q[++ tt] = i;
        if (i >= k - 1) b[i] = a[q[hh]];
    }
}

void get_min(int a[], int b[], int tot)
{
    int hh = 0, tt = -1;
    for (int i = 0; i < tot; i ++ )
    {
        if (hh <= tt && i - k + 1 > q[hh]) hh ++ ;
        while (hh <= tt && a[q[tt]] >= a[i]) tt -- ;
        q[++ tt] = i;
        if (i >= k - 1) b[i] = a[q[hh]];
    }
}

int main()
{
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < m; j ++ )
            scanf("%d", &w[i][j]);

    for (int i = 0; i < n; i ++ ) // 枚举每一行的最值
    {
        get_max(w[i], row_max[i], m);
        get_min(w[i], row_min[i], m);
    }

    int a[N], b[N], c[N], res = 1e9;
    for (int i = k - 1; i < m; i ++ )
    {
        for (int j = 0; j < n; j ++ ) a[j] = row_max[j][i];
        get_max(a, b, n);

        for (int j = 0; j < n; j ++ ) a[j] = row_min[j][i];
        get_min(a, c, n);

        for (int j = k - 1; j < n; j ++ )
            res = min(res, b[j] - c[j]);
    }
    printf("%d\n", res);
    return 0;
}

作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/1600528/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

4964. 子矩阵

#include <iostream>

using namespace std;

typedef long long LL;

const int N = 1010, mod = 998244353;

int n, m, A, B;
int w[N][N];
int row_min[N][N], row_max[N][N];
int q[N];

void get_max(int a[], int b[], int tot, int k) // k为窗口长度,tot为区间总长度
{
    int hh = 0, tt = -1;
    for (int i = 0; i < tot; i ++ )
    {
        if (hh <= tt && i - k + 1 > q[hh]) hh ++ ;
        while (hh <= tt && a[q[tt]] <= a[i]) tt -- ;
        q[++ tt] = i;
        if (i >= k - 1) b[i] = a[q[hh]];
    }
}

void get_min(int a[], int b[], int tot, int k) // k为窗口长度,tot为区间总长度
{
    int hh = 0, tt = -1;
    for (int i = 0; i < tot; i ++ )
    {
        if (hh <= tt && i - k + 1 > q[hh]) hh ++ ;
        while (hh <= tt && a[q[tt]] >= a[i]) tt -- ;
        q[++ tt] = i;
        if (i >= k - 1) b[i] = a[q[hh]];
    }
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &A, &B);
    for (int i = 0; i < n; i ++ )
        for (int j = 0; j < m; j ++ )
            scanf("%d", &w[i][j]);

    for (int i = 0; i < n; i ++ )
    {
        get_max(w[i], row_max[i], m, B);
        get_min(w[i], row_min[i], m, B);
    }

    int res = 0;
    int a[N], b[N], c[N];
    for (int i = B - 1; i < m; i ++ ) // 枚举每一列
    {
        for (int j = 0; j < n; j ++ ) a[j] = row_max[j][i];
        get_max(a, b, n, A);

        for (int j = 0; j < n; j ++ ) a[j] = row_min[j][i];
        get_min(a, c, n, A);

        for (int j = A - 1; j < n; j ++ )
            res = (res + (LL)b[j] * c[j]) % mod;
    }
    printf("%d\n", res);
    return 0;
}

作者:NFYD
链接:https://www.acwing.com/activity/content/code/content/6402744/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

标签:min,队列,tt,++,int,hh,滑动,数据结构,row
From: https://www.cnblogs.com/Tshaxz/p/17378211.html

相关文章

  • 消息队列Rabbitmq介绍、rabbitmq安装、基于queue实现生产者消费者、基本使用、消息安
    目录1消息队列Rabbitmq介绍2rabbitmq安装3基于queue实现生产者消费者4基本使用4.1发送者4.2消费者5消息安全(详见笔记)6持久化(详见笔记)7闲置消费(详见笔记)8发布订阅(详见笔记)9发布订阅高级之Routing(按关键字匹配)(详见笔记)1消息队列Rabbitmq介绍#消息队列 -......
  • 具有前后按钮切换+头图切换联动通用接口(应付不同的联动需要)的图片滑动效果
    -------scroll_tween.js----------CHRD.scroll.tween=function(){varTween={Quart:{easeOut:function(t,b,c,d){return-c*((t=t/d-1)*t*t*t-1)+b;}},Back:{easeOut......
  • web网页在手机端打开后左右可以滑动的css bug怎么解决
    web网页在手机端打开后左右可以滑动的cssbug怎么解决这个问题通常是由于在移动设备上使用了固定宽度的元素或容器而导致的。解决这个问题的一种方法是使用CSS媒体查询来检测移动设备,并将容器的宽度设置为100%。具体操作如下:@mediaonlyscreenand(max-width:768px){.cont......
  • jQuery效果-淡入淡出-滑动-回调
    <!DOCTYPEhtml><htmlxmlns="http://www.w3.org/1999/xhtml"><head><title></title><scriptsrc="../JQuery/jquery-1.8.0.min.js"></script><scriptsrc="JavaScript1.js">......
  • 3 第三章 内建数据结构、函数及文件
    Python编程:从入门到实践元组可以使用tuple函数将任意序列或迭代器转换为元组;可以使用+号连接元组来生成更长的元组;将元组乘以整数,则会生成含有多份拷贝的元组元组拆包In[15]:tup=(4,5,6)In[16]:a,b,c=tupIn[17]:b0ut[17]:5交换变量名:In[21]:a,b=1,......
  • Avalonia实现滑动加载
    Avalonia版本V0.10.18privatevoidScrollViewer_OnScrollChanged(object?sender,ScrollChangedEventArgse){varvm=(MainWindowViewModel)DataContext;vart=(ScrollViewer)sender;//Console.WriteLine($"偏移量:{t.O......
  • js数据结构变化 table动态列展示
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=......
  • Redis定长队列设计与实现
    业务背景:只展示最近10条礼物打赏动态,用户名+礼物名称不管在app端还是在web端,或多或少都有这样的需求,所谓技术方案的选型都是受限于实际的业务场景的,都是以解决实际业务为目的,由于刚开始这样的需求还是比较少的,所以采用了简单的方式实现了功能,但是随着业务扩大,重复的也会很多,再写......
  • Celery - 分布式任务队列
    Celery-分布式任务队列目录Celery-分布式任务队列1celery简介1.1什么是celery1.2celery架构(1)消息中间件messagebroker(2)任务执行单元worker(3)任务结果存储taskresultstore(4)使用场景2Celery安装与使用2.1安装2.2快速使用①第1步:创建celeryapp与创建任务②第2步......
  • 消息队列
    sys/msg.h#include<sys/msg.h>intmain(void){//创建消息队列//通过key创建或获取消息队列返回消息队列ID失败返回-1/**msgget创建或获取消息队列*key:ftok函数返回的key*msgflg标志位置*0-获取不......