这位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 ;
}

例题2 [POI2008]PLA-Postering

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的更多相关文章

  1. 浅谈Java中的栈和堆

    人们常说堆栈堆栈,堆和栈是内存中两处不一样的地方,什么样的数据存在栈,又是什么样的数据存在堆中? 这里浅谈Java中的栈和堆 首先,将结论写在前面,后面再用例子加以验证. Java的栈中存储以下类型数 ...

  2. 浅谈PHP数据结构之栈

    今天開始进阶自己的PHP,首先一切的编程语言都须要修炼自己的"内功",何为程序猿的"内功",我想大概就是数据结构和算法了吧 .毕竟是灵魂,是普通程序猿到高级程序 ...

  3. 虚拟化构建二分图(BZOJ2080 题解+浅谈几道双栈排序思想的题)

    虚拟化构建二分图 ------BZOJ2080 题解+浅谈几道双栈排序思想的题 本题的题解在最下面↓↓↓ 不得不说,第一次接触类似于双栈排序的这种题,是在BZOJ的五月月赛上. [BZOJ4881][ ...

  4. 莫队浅谈&题目讲解

    莫队浅谈&题目讲解 一.莫队的思想以及莫队的前置知识 莫队是一种离线的算法,他的实现借用了分块的思想.在学习莫队之前,本人建议学习一下分块,并对其有一定的理解. 二.莫队 现给出一道例题:bz ...

  5. 浅谈 Fragment 生命周期

    版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...

  6. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  7. 浅谈Linux中的信号处理机制(二)

    首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...

  8. 浅谈struts2之chain

    转自:http://blog.csdn.net/randomnet/article/details/8656759 前一段时间,有关chain的机制着实困绕了许久.尽管网上有许多关于chain的解说, ...

  9. 浅谈JAVA集合框架

    浅谈JAVA集合框架 Java提供了数种持有对象的方式,包括语言内置的Array,还有就是utilities中提供的容器类(container classes),又称群集类(collection cl ...

随机推荐

  1. uva 10806 Dijkstra, Dijkstra. (最小费最大流)

    uva 10806 Dijkstra, Dijkstra. 题目大意:你和你的伙伴想要越狱.你的伙伴先去探路,等你的伙伴到火车站后,他会打电话给你(电话是藏在蛋糕里带进来的),然后你就能够跑去火车站了 ...

  2. 【学生信息管理系统】EOF 和 BOF

    敲完学生信息管理系统时,在删除信息的时候,常常会出现下图这种错误,遇到问题就要解决这个问题.经过查阅理解了记录集Recordset的EOF和BOF属性,用这两个属性能够知道记录集中是否有信息存在. E ...

  3. My app status is Ready for Sale but I cannot see my app on the App Store. Why? 为什么审核通过后 appstore中搜不到我的app

    这是苹果的官方解答 The following factors could prevent your app from showing up on the App Store: Make sure t ...

  4. Andriod Atom x86模拟器启动报错。

    用Inter Atom模式的Android模拟器启动报一下错误: Starting emulator for AVD 'new' emulator: ERROR: x86 emulation curr ...

  5. sbt is a build tool for Scala, Java, and more

    http://www.scala-sbt.org/0.13/docs/index.html sbt is a build tool for Scala, Java, and more. It requ ...

  6. mysql----其他小技巧

    小技巧: min/max优化 在表中,一般都是经过优化的. 如下地区表 id area pid 1 中国 0 2 北京 1 ... 3115 3113 我们查min(id), id是主键,查Min(i ...

  7. ES6的相关新属性

    ES6  引入了类这个概念. 1.class……extends es6中的class与es5 中的function差不多: class Student extends People , student ...

  8. HDU3416 Marriage Match IV —— 最短路径 + 最大流

    题目链接:https://vjudge.net/problem/HDU-3416 Marriage Match IV Time Limit: 2000/1000 MS (Java/Others)    ...

  9. css盒子模型详解一

    什么是CSS的盒子模式呢?为什么叫它是盒子?先说说我们在网页设计中常听的属性名:内容(content).填充(padding).边框(border).边界(margin), CSS盒子模式都具备这些属 ...

  10. hdu acm 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2191 题目意思:有 资金 n 和 m 种类型的大米,对第 i 种类型的大米,价格.数量.袋数分别是: ...