单调队列和单调栈

单调队列和单调栈

一 单调队列

1.定义

单调队列是一种数据结构,用于存储的是在一个区间内的最大值,通常用于区间查询

2 实现方式

下面以存储最小值的单调队列为例,假设我们的区间范围是为n,那么在单调队列中,我们先不断的出队,去掉那些已经过时的元素,然后在让最新的元素从队尾进队,不断删除那些比它时间长并且比它还小的数

3 Example

假设现在用8个数要进入队列,求三个数长度的区间内的最小值

进队单调队列操作
333入队
111干掉3
21 22入队
51 2 55入队
92 5 91超时出队,9入队
65 69被6取代
76 75出队,7入队
111干掉所有

4 代码实现

struct  dull_queue
{
   int bottom;
   int top;
   int cnt;
   int length;
   struct elem
   {
     int value;
     int time;
   }elem[100];
   // top is the small one
   void Getin(int x)
   {
       struct elem temp;
       temp.time = cnt++;
       temp.value = x;
       while(bottom<=top&&elem[bottom].time+length<=cnt) bottom++;
     // 删除最早进入的一批
       while(bottom<=top&&temp.value<elem[top].value) top--;
     // 向队列里面加人
       elem[++top] = temp;
   }
   int Min()
   {
       return elem[bottom].value;
   }
  // 得到最小值
   void init()
   {
       bottom = 1;
       top = 0;
       cnt = 0;
   }
  // 初始化
}Small_queue;

5 单调队列模版题

题目出门左转

 其实这道题也可以使用单调队列进行解决,按照题意我们要找的其实就是 m a x ( f [ i − r ]   f [ i − l ] ) max(f[i-r]~f[i-l]) max(f[ir] f[il]),区间的长度为 r − l + 1 r- l+1 rl+1求区间内的最大值,只是这个区间相对于取值其实是有有个l的延迟,所以从i = L开始进行循环。在这道题里面有一些点是我们无法取到。针对这个情况我们去把f数组中的数初始化为一个极小值,如果他前面的数有正常值,那么他才能得到一只正常值,所以我们将 f [ 0 ] = 0 f[0] = 0 f[0]=0.

#include<iostream>
#include <string.h>
#define N 3001000
using namespace std;
int n,l,r;
int a[N];
int q[N];
int f[N];
int ans;
int main()
{
    int top = 1;
    int bottom = 1;
    scanf("%d%d%d",&n,&l,&r);
    for (int i = 0; i <= n; i++) scanf("%d",&a[i]);
    memset(f, 0xcf, sizeof(f));
    ans = f[0];
    int cnt = 0;
    f[cnt] = 0;
    for (int i = l; i <= n ; i++)
    {
       while(top<=bottom&& q[top] + r < i) top++;
      // 如果已经超时,那么将它退队
       while(top<=bottom&&f[cnt] >= f[q[bottom]]) bottom--;
      // 如果这个数比它大,那么从队尾到队首不断清理对手
       q[++bottom] = cnt;
      // 让他进入这个单调队列
       f[i] = f[q[top]] + a[i];
      // 得到f[i]这一点的数值
       cnt++;
    }
    for (int i = n - r + 1; i <= n; i++) ans = max(ans,f[i]);
    printf("%d",ans);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值