单调栈原理+练习

首先用一道题引出单调栈

码蹄集 (matiji.net)

首先画一个图演示山的情况:

最暴力的做法自然是O(n方)的双循环遍历,这么做的思想是求出当前山右侧有多少座比它小的山,遇见第一个高度大于等于它的就停止。

但是对于我们所求的答案数,可以换一个想法,即对于一座山,求出它左侧有多少座山可以看到它。

对于5;7可以看到它。

对于3;7,5可以看到它。

对于4;7,5可以看到它。

可以发现,即求左侧有多少比当前值大的山的个数,那么我们可以维护一个数据结构,使得每次加进来一个数,都保持递减的顺序,然后每次加入前,都计算它的size大小,进行累加。比如:

一开始7进入;

然后5准备进入,进入前检查是否进入后会破坏单调性,发现不会,那么将当前的size累加到sum里,sum当前为1。5进入,现在数据结构为7,5;

然后3准备进入,检查发现不会破坏单调性,sum累加当前size(2),sum现在为(3)。3进入,现在数据结构为7,5,3;

然后4准备进入,检查发现会破坏单调性,就把比4小的全部扔出,于是3出去了。这时候sum累加当前size(2),sum现在为(5),然后4进入,数据结构现在为7,5,4;

结果也符合手算结果。

发现此过程进和出都是在同一侧进行,那么最适合的数据结构自然是栈了。这样的思想就是单调栈。

以下是代码:

#include<iostream>
#include<stack>
#define int long long
using namespace std;
signed main() {int n, num, sum=0;//n为山脉个数;num为每次读入的山脉高度,sum为总和stack<int> stk;//栈,我们要使它单调cin >> n;for (int i = 1; i <= n; i++) {cin >> num;//下面的while循环即用来维护单调性,本题要严格单调递减//每次检查栈顶元素是否小于等于当前高度,如果是则弹出,直到为空或者栈顶高度大于当前高度while (!stk.empty() && stk.top() <= num)stk.pop();//总和累加,stk.size即左侧比当前山脉高的山脉,也即能看到当前山的个数sum += stk.size();//入栈,栈此时满足单调性stk.push(num);}cout << sum;
}

(因为数据范围的要求,得用long long)

下面还有几道练习题

码蹄集 (matiji.net)

这道题需要我们脑补出究竟是哪种情况可以使海报数变少。

最多的情况自然是墙的个数n,考虑下面的情况:

如果出现这种情况,即低-高-低,并且左侧和右侧低的墙高度相同,那么就可以减少一张海报了。

注意中间高的墙可以不止一道,只要是被两个同高且相对低的墙夹住,整体就可以减少一张海报。

同样,可以没有所谓的高墙,即两道相连的墙同高,那自然也可以减少一张海报数。

而如果是这种情况:(涂橙色的代表墙)

那么即使左右两侧高度相同,还是需要用三张海报,因为题目要求海报不能超出边界。

我们同样维护一个数据结构,如果新输入的墙高于当前墙,那么就可以加入;而如果小于当前墙,那么就需要检查是否存在低-高-低的情况了。低的墙的高度即取决于新输入的墙的高度,将数据结构里所有比低墙要高的墙都弹出;若遇到同高的墙,则代表海报数可以减1,同时也弹出在数据结构里的那个同高的墙;若遇到比我们选定的低墙还低的墙,就结束弹出操作,并把新输入的墙加入。

以下面的数据为例,数字代表墙的高度:

2,2,3,4,2;以下是数据结构内容的变化

  • 2(第一个2加入)
  • 2(读入第二个2,发现同高,把前一个弹出,同时记录可以减1个海报)
  • 2-3(读入3,直接加入)
  • 2-3-4(读入4,直接加入)
  • 2(读入最后一个2,发现比顶部的墙小,开始弹出,发现4,3,2都要弹出,并且记录可以减1个海报数)

最后发现可以减少两个海报,那么就需要5-2=3个海报,就可以覆盖上述例子。

最终我们发现,维护的数据结构最终依然是单调的,并且操作在同侧进行,所以依然是单调栈的做法。

代码如下,代码量是很少的,但是需要知道其中的思想

#include<bits/stdc++.h> 
using namespace std;
int n,ans,d,w;
stack<int> st;
int main( )
{cin>>n;for(int i=1;i<=n;i++){cin>>d>>w;//只要栈顶的墙的高度大于等于墙的高度,都需要弹出while(!st.empty()&&w<=st.top()){if(st.top()==w)//如果遇见同高的墙,记录可以减少一个海报数ans++;st.pop();//弹出}st.push(w);//此时栈里的墙都比当前墙矮(或者栈为空),此时可以加入,就不会破坏单调性}cout<<n-ans;//最终结果为n-ansreturn 0;
}

下一道题

码蹄集 (matiji.net)

以样例为例,这道题也可用单调栈完成

维护一个单调递增的栈,一旦新增系数不满足单调性,即代表它是第一个小于栈顶元素系数的值。

按步骤拆解:

一开始1,3入栈

之后读入-3,开始检查,发现-3小于栈顶元素,于是x三次方的系数就变成-3,然后弹出3;之后-3与栈顶1对比,发现-3小于栈顶元素,于是x四次方的系数就是-3,然后弹出1 。-3入栈。

6入栈

读入1,比6小,所以x的系数是1 。但是比下一个栈顶元素-3大,于是入栈,现在栈里有-3,1;

最后x的平方和x的0次方系数为0.

这里有个问题,就是如果栈里存放系数的话,经过弹栈入栈,就判断不了这个系数是属于哪个x次幂的了,所以我们栈里改为存放下标i,通过下标读入存放在数组的系数。

以下是代码:

#include<bits/stdc++.h> 
#define ll long long
const int MOD=99887765;
const int N=5e6+7;
using namespace std;
stack<int> st;
//a是原系数数组,b是新的系数数组
int n,x,a[N],b[N];
ll ans;
int main( )
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n>>x;for(int i=1;i<=n+1;i++){cin>>a[i];//如果读入的系数小于栈顶的系数(注意栈里存放的是下标,于是通过a[st.top()]来获得栈顶的系数)while(!st.empty()&&a[i]<a[st.top()]){b[st.top()]=a[i];//栈顶位置的x次幂的系数设置为当前读入的系数(是第一个小于原系数的值)//弹栈st.pop();}//注意如入栈的是下标st.push(i);}//其实最好是显式初始化一下b数组,把初始值都设为0,虽然不这样做默认初值也是0.这样没处理的下标的保存的新系数自动设为0//这里就是计算多项式了for(int i=1;i<=n+1;i++){ans=ans*x+b[i];ans=(ans%MOD+MOD)%MOD;}cout<<ans;return 0;
}

以上就是一些单调栈的简单示例了。

似乎可以总结出一个模板了:

1.循环读入新元素

2.用一个while循环,通过对比栈顶和新元素,来把不满足单调性的栈顶弹出

3.新元素压栈,保持单调性

至于题目有什么要求,就要在模板里进行一些其他操作了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/20475.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

codefun的蓝桥杯国赛之旅

前言 好久没有刷算法了&#xff0c;今天完成了我的蓝桥杯国赛之旅&#xff01; 总的来说&#xff0c;比赛的过程不是很顺利&#xff0c;只能ac两道题目&#xff0c;好多题都是有思路&#xff0c;但是要么是写不出来&#xff0c;要么是debug不出来&#xff0c;多重背包&#xf…

Docker(Centos7+)

先确定是否 Centos 7 及以上的版本 查看是否 ping 通外网 linux centos7运行下面的代码&#xff0c;基本上都可以正常安装 # 删除之前的docker残留 yum -y remove docker*yum install -y yum-utilsyum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/…

Controller类明明写了@CrossOrigin跨域注解,但还是有跨域问题

可能是写的过滤器干扰到了跨域处理。如&#xff1a; 此时&#xff0c;先注释掉过滤器注解&#xff0c;让其不生效&#xff0c;就可以避免干扰跨域处理了 不过&#xff0c;这只能暂时解决该问题&#xff0c;毕竟过滤器还是要用的&#xff0c;后续我再探索一下。。。。。。。

[个人笔记] 记录docker-compose使用和Harbor的部署过程

容器技术 第三章 记录docker-compose使用和Harbor的部署过程 容器技术记录docker-compose使用和Harbor的部署过程Harborhttps方式部署&#xff1a;测试环境部署使用自签名SSL证书https方式部署&#xff1a;正式环境部署使用企业颁发的SSL证书给Docker守护进程添加Harbor的SSL证…

ctfshow unserialize

开始反序列化 web255 是从cookie中unserialize得到实例&#xff0c;考虑修改cookie中键user的值 $result urlencode(serialize(new ctfShowUser())); 为何需要url编码呢&#xff0c;不url编码也能成。url编码是对称加密&#xff0c;编码也不影响 web256 考察!不完全等于&…

Ollama+OpenWebUI+Phi3本地大模型入门

文章目录 OllamaOpenWebUIPhi3本地大模型入门一、基础环境二、Ollama三、OpenWebUI Phi3 OllamaOpenWebUIPhi3本地大模型入门 完全不懂大模型的请绕道&#xff0c;相信我李一舟的课程比较适合 Ollama提供大模型运行环境&#xff0c;OpenWebUI提供UI&#xff0c;Phi3就是那个大…

【学习】自动化测试与单元测试框架的差异化解析

在软件开发的世界中&#xff0c;质量保证是构建可靠、健壮应用程序的关键一环。在这个过程中&#xff0c;自动化测试和单元测试框架是确保代码质量的两种重要工具。尽管它们在目标上有着共同点——提高软件测试的效率和有效性&#xff0c;但它们在应用场景、功能特点以及实现方…

Vue基础知识:vue3 对于 ref 值的类型定义

vue3 对于 ref 值的类型定义 从 vue2 到 vue3 之后&#xff0c;所有变量值都需要添加 ref() const name ref(kyle)意思是 vue3 变量由 vue 来控制&#xff0c;上面的 name 变量值并不是原始的字符串 kyle 而是被套了一层类型为 Ref 的对象。 使用的时候 console.log(name.v…

Day45 动态规划part05

LC1049最后一块石头重量II(未掌握) 未掌握分析&#xff1a;其实本题跟LC416分割等和子集类似&#xff0c;本质上题目的要求是尽量让石头分成重量相同的两堆&#xff0c;相撞之后剩下的石头最小&#xff0c;也就是01背包问题weight和value都是stones数组&#xff0c;题目可以看…

深度学习-02-创建变量的函数

深度学习-02-创建变量的函数 本文是《深度学习入门2-自製框架》 的学习笔记&#xff0c;记录自己学习心得&#xff0c;以及对重点知识的理解。如果内容对你有帮助&#xff0c;请支持正版&#xff0c;去购买正版书籍&#xff0c;支持正版书籍不仅是尊重作者的辛勤劳动&#xff0…

Go-Admin后台管理系统源码(GO+VUE)编译与部署

1.克隆源码: # Get backend code git clone https://github.com/go-admin-team/go-admin.git# Get the front-end code git clone https://github.com/go-admin-team/go-admin-ui.git3.下载并安装GO开发环境: 3.编译管理后台后端 # Enter the go-admin backend project cd ./…

Pytorch索引、切片、连接

文章目录 1.torch.cat()2.torch.column_stack()3.torch.gather()4.torch.hstack()5.torch.vstack()6.torch.index_select()7.torch.masked_select()8.torch.reshape9.torch.stack()10.torch.where()11.torch.tile()12.torch.take()13.torch.scatter() 1.torch.cat() torch.cat(…

基于排队理论的客户结账等待时间MATLAB模拟仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 排队系统的组成 4.2 基本概念 4.3 常见的排队模型 5.完整程序 1.程序功能描述 基于排队理论的客户结账等待时间MATLAB模拟仿真&#xff0c;分析平均队长&#xff0c;平均等待时长&…

智慧交通视频AI监控识别解决方案

背景分析 随着社会的进步和科技的不断发展&#xff0c;互联网技术和AI视觉分析技术日益成熟&#xff0c;为传统交通监控领域带来了新的发展机遇。AI视觉分析技术的引入&#xff0c;不仅提升了交通监控的智能化和自动化水平&#xff0c;还显著减轻了交管部门的工作负担&#xf…

雷卯解析AECQ101与AECQ200

AEC&#xff08;汽车电子委员会&#xff09;推出了AECQ101和AECQ200这两项行业标准&#xff0c;作为汽车电子元件的“品质通行证”。上海雷卯已率先申请AECQ101证书。 鉴于有些客户不清楚AECQ101和AECQ200的区别&#xff0c;哪些供应商应该提供什么类别证书。本文将带您解析这…

本地知识库开源框架Fastgpt、MaxKB产品体验

本地知识库开源框架Fastgpt、MaxKB产品体验 背景fastgpt简介知识库共享部署 MaxKB总结 背景 上一篇体验了Quivr、QAnything两个开源知识库模型框架&#xff0c;这次介绍两款小众但是体验比较好的产品。 fastgpt 简介 FastGPT 是一个基于 LLM 大语言模型的知识库问答系统&am…

第四范式Q1业务进展:驰而不息 用科技锻造不朽价值

5月28日&#xff0c;第四范式发布今年前三个月的核心业务进展&#xff0c;公司坚持科技创新&#xff0c;业务稳步拓展&#xff0c;用人工智能为千行万业贡献价值。 今年前三个月&#xff0c;公司总收入人民币8.3亿元&#xff0c;同比增长28.5%&#xff0c;毛利润人民币3.4亿元&…

python猜数字游戏

猜数字游戏 计算机随机产生一个1~100的随机数&#xff0c;人输入自己猜的数字&#xff0c; 计算机给出对应的提示“大一点”&#xff0c;”小一点“或”恭喜你猜对了“&#xff0c;直到猜中为止。 如果猜的次数超过7次&#xff0c;计算机温馨提示“智商余额明显不足” import …

SLAM精度评估—evo

evo是一款用于SLAM轨迹精度的评估工具。核心功能是&#xff08;1&#xff09;能够绘制&#xff08;传感器运动&#xff09;轨迹&#xff0c;&#xff08;2&#xff09;评估估计轨迹与真值&#xff08;ground truth&#xff09;的误差。evo支持多种数据集的轨迹格式(TUM、KITT、…

用户购物性别模型标签(USG)之决策树模型

一、USG模型引入: 首先了解一下&#xff0c;如何通过大数据来确定用户的真实性别&#xff0c; 经常谈论的用户精细化运营&#xff0c;到底是什么? 简单来讲&#xff0c;就是将网站的每个用户标签化&#xff0c;制作一个属于用户自己的网络身份证。然后&#xff0c;运营人员 通…