首页 > 其他分享 >浅谈单调栈

浅谈单调栈

时间:2023-12-23 09:02:23浏览次数:35  
标签:gt 浅谈 int lt ch 矩形 单调

单调栈,顾名思义,具有单调性的栈。

  • 单调,指满足一个序列是一个从小到大的序列或从大到小的序列。

  • 栈(\(stack\))是以一种线性存储结构,它具有以下特点:栈中的数据元素遵守“先进后出(\(First\ in\ Last\ out\))”的原则,简称 FILO 结构;限定只能在栈顶进行插入和删除操作。

所以,何为单调栈,我们只需要维护一个具有单调性的栈

如何维护一个具有单调性的栈,我们以单调递增栈为例。

  • 将一个元素插入单调栈时,为了维护栈的单调性,需要在保证将该元素插入到栈顶后整个栈满足单调性的前提下弹出最少的元素

  • 我们来模拟一下单调栈的过程。

  • 例如,现在栈中自底向顶的序列为 \(\{0,2,5,10,32\}\)。

    • 现在,我们需要将 \(3\) 加入栈中。
      • 我们比较 \(0\) 和 \(3\) 的大小,发现 \(0<3\),所以将 \(0\) 弹出栈。
      • 我们接着比较 \(2\) 和 \(3\) 的大小,发现 \(2<3\),所以将 \(2\) 弹出栈。
      • 我们接着比较 \(5\) 和 \(3\) 的大小,发现 \(5>3\),所以 \(3\) 进入栈。比较结束。
      • 此时栈中自底向顶的序列为 \(\{3,5,10,32\}\)。
    • 接着,我们需要将 \(20\) 加入栈中。
      • 我们比较 \(20\) 和 \(3\) 的大小,发现 \(3<20\),所以将 \(3\) 弹出栈。
      • 我们接着比较 \(20\) 和 \(5\) 的大小,发现 \(5<20\),所以将 \(5\) 弹出栈。
      • 我们接着比较 \(20\) 和 \(32\) 的大小,发现 \(32>20\),所以 \(20\) 进入栈。比较结束。
      • 此时栈中自底向顶的序列为 \(\{20,32\}\)。
    • 接着,我们需要将 \(50\) 加入栈中。
      • 我们比较 \(50\) 和 \(32\) 的大小,发现 \(50>32\),所以将 \(32\) 弹出栈。
      • 此时,栈为空,所以 \(50\) 进入栈。

所以,我们用伪代码描述如下:

insert x
while !sta.empty() &amp;&amp; sta.top()&lt;x
    sta.pop()
sta.push(x)
//by oi-wiki.org

接下来,讲几道比较经典的题:

  • HISTOGRA - Largest Rectangle in a Histogram
    • 如果是递增的我们就放着不管,以后来处理。如果说下一个高度更小,那么用它所构成的矩形的高度不可能超过它自己,而后面的矩形想要和前面的矩形拼接的话,高度也不能超过它。
    • 这样子的话,我们可以用上面的方法更新比当前矩形高的矩形的答案再将它们合并。
    • 我们可以借助单调性处理问题的思想在于及时排除不可能的选项,保持策略集合的高度有效性和秩序性
    • 我们从左到右读入矩形,如果当前矩形比栈顶矩形高,即满足单调递增,进栈。否则不断去除栈顶,直至栈空或栈顶高度低于当前矩形。在此过程中,我们累计被弹出的矩形的宽度和(用于计算答案与合并),用 \(高度\times累计宽度\) 更新答案。而后,将一个宽度为累计宽度,高度为当前矩形的矩形入栈。结束,将剩余矩形弹出,和上面一样更新答案;
#include &lt;bits/stdc++.h&gt;
using namespace std;
#define ll long long
const int MAXN=1e7+5;
ll a[MAXN],ans;
int j;
stack&lt;int&gt; s;
inline ll read(){
    int x=0,f=1;
    ll ch=getchar();
    while(ch&lt;'0'||ch&gt;'9'){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch&gt;='0'&amp;&amp;ch&lt;='9'){
        x=(x&lt;&lt;1)+(x&lt;&lt;3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
int main(){
    int n=read();
    for(int i=0;i&lt;n;++i){
    	a[i]=read();
	} 
    while (j&lt;=n){
        if (s.empty() || a[s.top()]&lt;=a[j]){
        	s.push(j++);
		}
    	else{
            ll temp=s.top(),wide;
			s.pop();
			if (s.empty()) wide=j;
			else wide=(j-s.top()-1);
            ans=max(ans,a[temp]*wide);
        }
    }
    printf("%lld\n",ans);
}
//by sjh
#include &lt;bits/stdc++.h&gt;
using namespace std;
const int MAXN=5e4+5;
struct node{
	int h,v;
}p[MAXN];
int f[MAXN];
stack&lt;pair&lt;int,int&gt; &gt; s;
int main(){
	int n;
	scanf("%d",&amp;n);
	for(int i=1;i&lt;=n;++i){
		scanf("%d %d",&amp;p[i].h,&amp;p[i].v);
	}	
	for(int i=1;i&lt;=n;++i){
		if (!s.size()) s.push({p[i].h,p[i].v});
		else{
			while (!s.empty()){
				pair&lt;int,int&gt; t=s.top();
				if (t.first&lt;p[i].h){
					s.pop();
					f[i]+=t.second;
				}
				else break;
			}
			s.push({p[i].h,p[i].v});
		}
	}
	while (!s.empty()){
		s.pop();
	}
	for(int i=n;i&gt;=1;--i){
		if (!s.size()) s.push({p[i].h,p[i].v});
		else{
			while (!s.empty()){
				pair&lt;int,int&gt; t=s.top();
				if (t.first&lt;p[i].h){
					s.pop();
					f[i]+=t.second;
				}
				else break;
			}
			s.push({p[i].h,p[i].v});
		}
	}
	int ans=0;
	for(int i=1;i&lt;=n;++i){
		ans=max(ans,f[i]);
	}
	printf("%d\n",ans);
	return 0;
}

标签:gt,浅谈,int,lt,ch,矩形,单调
From: https://www.cnblogs.com/Jasonshan10/p/17922677.html

相关文章

  • 浅谈C++STL(Standard Template Library,标准模板库)
    2.1STL的诞生长久以来,软件界一直希望建立一种可重复利用的东西C++的面向对象和泛型编程思想,目的就是复用性的提升大多情况下,数据结构和算法都未能有一套标准,导致被迫从事大量重复工作为了建立数据结构和算法的一套标准,诞生了STL2.2STL基本概念STL(StandardTemplateLibrary,标......
  • 浅谈WPF之DataGrid过滤,分组,排序
    使用过Excel的用户都知道,Excel可以方便的对数据进行分组,过滤,排序等操作,而在WPF中,默认提供的DataGrid只有很简单的功能,那么如何才能让我们开发的DataGrid,也像Excel一样具备丰富的客户端操作呢?今天就以一个简单的小例子,简述如何在WPF中实现DataGrid的过滤,筛选,排序等功能。仅供学习分......
  • 浅谈C++类型转换函数
    reinterpret_castreinterpret_cast<newtype>(expression)将一个类型的指针转换为另一个类型的指针,它允许从一个指针转换为整数类型。voidtest01(){ chara=0; int*p=reinterpret_cast<int*>(&a); //不安全}const_cast常量const指针与普通指针之间的相互转化。如果不用......
  • 单调栈求解算法
    例题:503. 下一个更大元素II给定一个循环数组 nums ( nums[nums.length-1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一......
  • 从西工大安全事件浅谈特权账号管理系统
    去年9月,国家计算机应急处理中心发布《西北工业大学遭美国NSA网络入侵事件调查报告(之一)》(以下简称“西工大事件报告”),以充分详实的证据揭示了美国NSA使用41种武器,先后使用了遍布17个国家的54台跳板机和代理服务器,对我国包括西北工业大学等多个重要数据设施网络系统进行了长时间的浸......
  • Java线程池使用浅谈
    1. 线程池相关基本概念任务(Task):任务是线程池中要执行的工作单元。任务可以是实现了 Runnable 接口或 Callable 接口的对象。Runnable 任务没有返回值,而 Callable 任务可以返回一个结果。线程池管理器(ThreadPoolManager):线程池管理器是用于创建和管理线程池的组件。......
  • 浅谈 USB 枚举过程
    浅谈USB枚举过程一、概述  在我们的产品应用中,不管是鼠标、键盘、还是其他产品等等,有很多设备都离不开USB接口,我们不仅要清楚如何进行USB的硬件设计,也要懂得USB的具体协议规范,才能看懂对应的代码流程。那么下面我们就来了解下USB的枚举流程。二、USB设备状态......
  • 【拜谢tgt】浅谈微积分在高中数学中的应用
    pdf版本(渲染较好)浅谈微积分在高中数学中的应用前言本文仅作为各类题型或技巧的归纳,以在高考中应用为目的。A\(\operatorname{L'H\hatopital's\;rule}\)不严格地说,洛必达法则就是在\(\frac{0}{0}\)型和\(\frac{\infty}{\infty}\)型时,有:\[\begin{aligned}\lim_{x\t......
  • 浅谈分布式事务
    事务:事务是指由一组操作组成的一个工作单元,这个工作单元具有原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)。原子性:执行单元中的操作要么全部执行成功,要么全部失败。如果有一部分成功一部分失败那么成功的操作要全部回滚到执行前的状态。一致性:执行......
  • 浅谈 Socket.D 与响应式编程
    一、Socket.D的主要特性首先,Scoket.D是高效一个二进制的网络通讯协议(官方我讲法是:基于事件和语义消息流的网络应用协议),能够满足很多场景下使用。其次,Scoket.D是温和的响应式(采用回调风格)。1、三种通讯模式send只是发送(发送后不管了)发送一个请求,无需为这个请求发送答复报......