浅谈单调栈 By cellur925
这位dalao的单调栈文章很棒!我写的是他的题单233. http://www.cnblogs.com/COLIN-LIGHTNING/p/8474668.html
一、单调栈的一般写法
for(int i=;i<=n;i++)
{
int x=;
scanf("%d",&x);
while(x>=sta[top]&&top)
top--;
sta[++top]=x;
}
而各种各样繁杂的题目正是在这个基础上维护一些其他的信息。
二、注意事项
栈不能为空。要随时注意,否则RE。
计数类可能会用到$longlong$。
三、例题详解
例题0 LIS(最长上升子序列)辣个$nlogn$的算法其实本质上就是单调栈...
例题1 音乐会的等待
N个人正在排队进入一个音乐会。人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人。队列中任意两个人A和B,如果他们是相邻或他们之间没有人比A或B高,那么他们是可以互相看得见的。
写一个程序计算出有多少对人可以互相看见。(注意,是互相看见)
维护一个单调不增的栈。(因为两个之间没有比他们高的人时他们才能互相看见,中间隔等高个人时是可以互相看见的)
(注意!脑子别晕!233,这是栈!不是队列!栈顶是最后加的!)
当新来的人身高小于栈顶,直接进来。答案在栈非空的情况下加1,这算的是栈顶和当前元素这对。(满足相邻的条件)
当新来的人身高大于栈顶,弹栈直到满足小于(或等于)。因为维护的单调递减的栈,而新生还很高,所以自然能看得见。这里每次弹栈都加上那个元素的个数(具体接下来会讲)。满足性质后,再和栈顶比较。
当新来的人身高等于栈顶,弹栈直到小于。我们把和它相等的都弹走,但是要注意记上和它相等的数出现的次数,以便之后使用,因为相等,所以肯定看的见,为接下来记录了信息(解释了第二种情况)。满足性质后,再和栈顶比较。
综上,我们看出每个元素最多入栈出栈一次,复杂度$O(N)$,每次入栈后,都要在栈不为空的情况下,答案++,因为栈顶(最外面的元素)一定能看见新来的元素。
Code
#include<cstdio>
#include<algorithm> using namespace std;
typedef long long ll; int n,top,x,num;
struct node{
int val,num;
}sta[];
ll ans; int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&x);
node p=(node){x,};
while(x>=sta[top].val&&top)
{
ans+=sta[top].num;
if(sta[top].val==x) p.num+=sta[top].num;
//虽然弹走了 记下 以后用得到
top--;
}
if(top) ans++;
sta[++top]=p;
}
printf("%lld",ans);
return ;
}
Byteburg市东边的建筑都是以旧结构形式建造的:建筑互相紧挨着,之间没有空间.它们共同形成了一条长长的,从东向西延伸的建筑物链(建筑物的高度不一).Byteburg市的市长Byteasar,决定将这个建筑物链的一侧用海报覆盖住.并且想用最少的海报数量,海报是矩形的.海报与海报之间不能重叠,但是可以相互挨着(即它们具有公共边),每一个海报都必须贴近墙并且建筑物链的整个一侧必须被覆盖(意思是:海报需要将一侧全部覆盖,并且不能超出建筑物链,即不能盖着没有海报存在的地方)
读完题后,我们很快就会发现,那个宽度的条件其实是没用的,我们只需要考虑高度就行了。设开始我们需要海报的数量等于矩形的数量,我们再一点点减。那么,我们便可以维护一个高度单调递增的栈,在弹栈过程中,若遇到和自己相等的高度,就将答案减去1,因为如图,我们可以横着盖,我们只需要再把高出来的(於出来的)用一张海报即可。

Code
#include<cstdio>
#include<algorithm> using namespace std; int n,ans,top;
int sta[]; int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
int y=,x=;
scanf("%d%d",&y,&x);
while(top&&x<=sta[top])
{
if(x==sta[top]) ans++;
top--;
}
sta[++top]=x;
}
printf("%d",n-ans);
return ;
}
以上都是一些比较简单的线性问题。接下来我们要看的是那些或者在二维上,或者掺杂入实际的面积,这些更复杂的问题。
例题3 玉蟾宫 哎又要看Freda学姐和rainbowcat虐狗了
其实这题还有悬线法,是求最大子矩阵的一个方法,这里就不再说了==(大坑)
抽象一下本题的模型:有障碍点的情况下的最大子矩形。
虽然这题是二维的了,但是我们还可以分别计算情况。
首先,我们用一个$f[i][j]$表示在$(i,j)$点,前$i$行,第$j$列,以第$i$行结尾,连续的‘F’个数。(最大可延伸距离)
行与行之间的问题就解决了。
然后在同一行,不同列上的问题就可以用单调栈(单调递增栈)来维护了。
单调栈中存储两个信息。此单位高度$height$,和对应可控宽度$wid$(对应可控我觉得说的非常准确)
同理,我们当前的高度(f数组)大于栈顶时,直接把它压入栈。
否则,就一直弹栈。弹栈的时候,我们要记录矩形的信息来更新答案。它的$wid$是所有弹栈元素的$wid$+1.(因为我们继承了之前的信息,这部分 到之后也是可以用的。因为被弹栈的元素高度均大于当前元素,在可控范围内。)
之后更新答案即可。枚举到最后一列后,把栈都搞空。
Code
#include<cstdio>
#include<algorithm> using namespace std; int n,m,ans,top,tmp,neww;
struct node{
int height,wid;
}sta[];
char qwq[],mapp[][],f[][]; void work(int x)
{
top=;tmp=;neww=;
sta[].height=f[x][];
sta[].wid=;
for(int i=;i<=m;i++)
{
tmp=;
while(f[x][i]<=sta[top].height&&top)
{
tmp+=sta[top].wid;
neww=max(neww,tmp*sta[top].height);
top--;
}
sta[++top].height=f[x][i];
sta[top].wid=tmp+;
}
tmp=;
while(top)
{
tmp+=sta[top].wid;
neww=max(neww,tmp*sta[top].height);
top--;
}
ans=max(ans,neww);
} int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
scanf("%s",qwq+),mapp[i][j]=qwq[];
if(mapp[i][j]=='F') f[i][j]=f[i-][j]+;
}
for(int i=;i<=n;i++) work(i);
printf("%d",ans*);
return ;
}
例题4 Largest Rectangle in a Histogram
在一条水平线上给出若干连续矩形,求包含于这些矩形的并集内部最大矩形的面积。
这应该是单调栈的典型题目惹qwq。
我们假设,到现在为止,读入的矩形高度都是递增的,那么如果突然读入了一个比上一个矩形矮的矩形,那么之前高的矩形搞出来就没有用了(於出来了)

打叉的部分就没用了。没用就删去啊,所以我们在做的事情就是维护一个单调递增的矩形序列。与上题相似,弹矩形的时候,我们同样要维护弹出矩形的答案。
其实这和上一题差不多啦qwq。
Code
#include<cstdio>
#include<algorithm>
#include<cstring> using namespace std;
typedef long long ll; int n,top,x,tmp;
ll ans;
struct node{
int height,wid;
}sta[]; int main()
{
while(scanf("%d",&n)!=EOF&&n)
{
for(int i=;i<=n;i++)
{
tmp=;
scanf("%d",&x);
while(x<=sta[top].height&&top)
{
tmp+=sta[top].wid;
ans=max(ans,1ll*tmp*sta[top].height);
top--;
}
sta[++top].height=x;
sta[top].wid=tmp+;
}
tmp=;
while(top)
{
tmp+=sta[top].wid;
ans=max(ans,1ll*tmp*sta[top].height);
top--;
}
printf("%lld\n",ans);
top=;ans=;
memset(sta,,sizeof(sta));
}
return ;
}
这种更新面积(我也不知道怎么总结)的问题,最后一定要记得把栈搞空啊qwq。
单调栈先告一段落,下一次来看单调队列qwq。
浅谈单调栈 By cellur925的更多相关文章
- 浅谈Java中的栈和堆
人们常说堆栈堆栈,堆和栈是内存中两处不一样的地方,什么样的数据存在栈,又是什么样的数据存在堆中? 这里浅谈Java中的栈和堆 首先,将结论写在前面,后面再用例子加以验证. Java的栈中存储以下类型数 ...
- 浅谈PHP数据结构之栈
今天開始进阶自己的PHP,首先一切的编程语言都须要修炼自己的"内功",何为程序猿的"内功",我想大概就是数据结构和算法了吧 .毕竟是灵魂,是普通程序猿到高级程序 ...
- 虚拟化构建二分图(BZOJ2080 题解+浅谈几道双栈排序思想的题)
虚拟化构建二分图 ------BZOJ2080 题解+浅谈几道双栈排序思想的题 本题的题解在最下面↓↓↓ 不得不说,第一次接触类似于双栈排序的这种题,是在BZOJ的五月月赛上. [BZOJ4881][ ...
- 莫队浅谈&题目讲解
莫队浅谈&题目讲解 一.莫队的思想以及莫队的前置知识 莫队是一种离线的算法,他的实现借用了分块的思想.在学习莫队之前,本人建议学习一下分块,并对其有一定的理解. 二.莫队 现给出一道例题:bz ...
- 浅谈 Fragment 生命周期
版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...
- 浅谈Java的throw与throws
转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...
- 浅谈Linux中的信号处理机制(二)
首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...
- 浅谈struts2之chain
转自:http://blog.csdn.net/randomnet/article/details/8656759 前一段时间,有关chain的机制着实困绕了许久.尽管网上有许多关于chain的解说, ...
- 浅谈JAVA集合框架
浅谈JAVA集合框架 Java提供了数种持有对象的方式,包括语言内置的Array,还有就是utilities中提供的容器类(container classes),又称群集类(collection cl ...
随机推荐
- mysql语法、特殊符号及正則表達式的使用
http://blog.csdn.net/pipisorry/article/details/46773545 sql语言 结构化的查询语言.(Structured Query Language),是 ...
- AML LCD debuged
root@k101:/ # cat /sys/class/lcd/debug Usage: echo basi ...
- coco2d-x 3.0游戏实例学习笔记 《跑酷》 第二步---游戏界面&全新的3.0物理世界
说明:这里是借鉴:晓风残月前辈的博客,他是将泰然网的跑酷教程.用cocos2d-x 2.X 版本号重写的,眼下我正在学习cocos2d-X3.0 于是就用cocos2d-X 3.0重写.并做相关笔记 ...
- homebrew -v 或homebrew -doctor报错请检查 .bash_profile是否有误
homebrew -doctor报错: /usr/local/Library/Homebrew/global.rb:109:in `split': invalid byte sequence in U ...
- Android — 长按ListView 利用上下文菜单(ActionMode) 进行批量事件处理
好久没写博客拉``````` 近期最终略微闲一点了``````` 无聊拿手机清理短信.发现批量事件的处理还是挺管用的`````` 那么自己也来山寨一记看看效果吧````` 闲话少说,首先,我们来看下手 ...
- COGS28 [NOI2006] 最大获利[最大权闭合子图]
[NOI2006] 最大获利 ★★★☆ 输入文件:profit.in 输出文件:profit.out 简单对比时间限制:2 s 内存限制:512 MB [问题描述] 新的技术正冲击着手 ...
- Cocos2d-js异步图片加载
这里说的是在需要的使用加载图片,比如游戏中的某个关卡的图片,不用在游戏一开始就加载(万一用户玩不到那关,岂不是很冤,流量费了那么多),否则 载入速度也慢.这种方式加载资源要用到cc.loader官方文 ...
- adb常用命令整理
adb connect <IPAddress:Port> //通过指定的IP地址及端口连接设备 adb devices //显示所有已连接的设备 adb install <Pac ...
- CH 5105 Cookies(贪心+DP)
\(CH 5105 Cookies\) \(solution:\) 真是好题一道!这道题我想了很久很久,就得这一题可以直接完全贪心,可惜最后还是失败了,但是对贪心的深入思考也换来了一个最优解方案.然后 ...
- poj 3017 Cut the Sequence(单调队列优化DP)
Cut the Sequence \(solution:\) 这道题出的真的很好,奈何数据水啊! 这道题当时看得一脸懵逼,说二分也不像二分,说贪心也不像贪心,说搜索吧这题数据范围怎么这么大?而且这题看 ...