单调栈【学习笔记】
单调栈可以用来解决“对一个序列,求出每个元素向左和向右遇到的第一个比它大的元素”
例题1:P1901 发射站
Solution:
模板题
左右两边是对称的,可以用同样的方式分别处理,以向右为例
单调栈中压入待求解的元素,那么如果新加入的元素i比栈顶元素s[top]大,就把栈顶答案标记为i,同时将栈顶弹出。重复上述过程直到栈顶大于i或栈空
因此,单调栈中元素单调不升
例题2:P1823 [COI2007] Patrik 音乐会的等待
题目描述
n个人正在排队进入一个音乐会。人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人。
队列中任意两个人a和b,如果他们是相邻或他们之间没有人比a或b高,那么他们是可以互相看得见的。
计算出有多少对人可以互相看见。
Solution:
首先记录所有相邻的人数,为n-1
接下来考虑如何计算所有不相邻且中间元素均小于等于两端的数对个数
对于每个数对,先固定一个端点,以左端点为例,将所有左端点压入栈,对于每个左端点求满足条件的数对个数,然后累加求和即可
具体地,
若当前元素i大于栈顶元素s[top]:如果当前元素i还未弹出元素,那么栈顶元素的ans=0,总答案不变,否则,栈顶元素的ans++,总答案加上栈顶元素的元素个数;弹出栈顶(因为栈顶已计算完);
若当前元素i等于栈顶元素:若当前元素i还未弹出元素,总答案加上栈顶元素的个数减一,否则总答案加上栈顶元素个数,若栈底元素大于当前元素,总答案加一;栈顶元素个数加一;
若当前元素i小于栈顶元素:直接将i压入栈
因此单调栈维护一个关键字单调不升的二元组(node,cnt),表示编号和个数
单调栈还可以用来优化dp
例题1:P3400 仓鼠窝

浙公网安备 33010602011771号