单调队列《滑动窗口》

#include <iostream>

using namespace std;

const int N = 100010;

int m;
int q[N], hh, tt = -1;//hh表示队头,tt表示队尾

int main()
{
    cin >> m;

    while (m -- )
    {
        string op;
        int x;

        cin >> op;
        if (op == "push")
        {
            cin >> x;
            q[ ++ tt] = x;//队尾插入
        }
        else if (op == "pop") hh ++ ;//弹出
        else if (op == "empty") cout << (hh <= tt ? "NO" : "YES") << endl;
        else cout << q[hh] << endl;
        //判断是不是空的
        //if(hh<tt)
        // cout <<"不空";
        // else
        // cout << "空"
        
        //取出队头尾元素
        //q[hh];
        //q[tt];
        
    }

    return 0;
}

单调队列《滑动窗口》

#include <iostream>

using namespace std;

const int N = 1000010;

// a 数组存储输入的数字,q 数组作为滑动窗口的双端队列
int a[N], q[N];

int main()
{
    int n, k;
    // 读取数组长度 n 和窗口大小 k
    scanf("%d%d", &n, &k);
    // 读取数组中的 n 个数字
    for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);

    // 计算滑动窗口的最小值
    int hh = 0, tt = -1; // hh 为队列头,tt 为队列尾
    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;

        // 当窗口大小达到 k 时,输出当前窗口的最小值
        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;

        // 当窗口大小达到 k 时,输出当前窗口的最大值
        if (i >= k - 1) printf("%d ", a[q[hh]]);
    }

    puts(""); // 换行

    return 0;
}

 

// 执行过程:

// 计算最小值:

// 初始时,队列 q 是空的,hh 为 0,tt 为 -1。
// 遍历 a 数组:
// i = 0: a[i] = 1,队列为空,将 i 0 加入队列 q。队列 [0]。窗口小于 k,继续。
// i = 1: a[i] = 3,将 i 1 加入队列 q。队列 [0, 1]。窗口小于 k,继续。
// i = 2: a[i] = -1,将队列尾的元素(索引 1)移除,因为 a[1] >= -1。将 i 2 加入队列 q。队列 [0, 2]。窗口已满,输出最小值 a[0] = 1。
// i = 3: a[i] = -3,将队列尾的元素(索引 2)移除,因为 a[2] >= -3。将 i 3 加入队列 q。队列 [3]。输出最小值 a[3] = -3。
// i = 4: a[i] = 5,将 i 4 加入队列 q。队列 [3, 4]。输出最小值 a[3] = -3。
// i = 5: a[i] = 3,将 i 5 加入队列 q。队列 [3, 4, 5]。移除队列头元素,因为窗口不再包含索引 3。输出最小值 a[4] = -3。
// i = 6: a[i] = 6,将 i 6 加入队列 q。队列 [4, 5, 6]。输出最小值 a[5] = 3。
// i = 7: a[i] = 7,将 i 7 加入队列 q。队列 [5, 6, 7]。输出最小值 a[6] = 3。
// 最终最小值序列为: -1 -3 -3 -3 3 3
// 计算最大值:

// 初始时,队列 q 是空的,hh 为 0,tt 为 -1。
// 遍历 a 数组:
// i = 0: a[i] = 1,队列为空,将 i 0 加入队列 q。队列 [0]。窗口小于 k,继续。
// i = 1: a[i] = 3,将队列尾的元素(索引 0)移除,因为 a[0] < 3。将 i 1 加入队列 q。队列 [1]。窗口小于 k,继续.
// i = 2: a[i] = -1,将 i 2 加入队列 q。队列 [1, 2]。窗口已满,输出最大值 a[1] = 3。
// i = 3: a[i] = -3,将 i 3 加入队列 q。队列 [1, 2, 3]。移除队列头元素,因为窗口不再包含索引 1。输出最大值 a[2] = -1。
// i = 4: a[i] = 5,将队列尾的元素(索引 3)移除,因为 a[3] < 5。将 i 4 加入队列 q。队列 [4]。输出最大值 a[4] = 5。
// i = 5: a[i] = 3,将 i 5 加入队列 q。队列 [4, 5]。输出最大值 a[4] = 5。
// i = 6: a[i] = 6,将队列尾的元素(索引 5)移除,因为 a[5] < 6。将队列尾的元素(索引 4)移除,因为 a[4] < 6。将 i 6 加入队列 q。队列 [6]。输出最大值 a[6] = 6。
// i = 7: a[i] = 7,将队列尾的元素(索引 6)移除,因为 a[6] < 7。将 i 7 加入队列 q。队列 [7]。输出最大值 a[7] = 7。
// 最终最大值序列为: 3 3 5 5 6 7

  • 10
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值