单调栈、单调队列 思路及例题

单调栈

单调栈目的并不在于存储所有入栈元素。

对于一个单调递增栈,如果栈为空或入栈元素值小于栈顶元素值,则入栈;

否则,如果入栈则会破坏栈的单调性,则需要把比入栈元素小的元素全部出栈。

单调递减栈反之同理。

及时排除不可能的选项,保持策略集合的高度有效性和秩序性

时间复杂度 \(O(n)\)。(每个元素至多入栈一次,出栈一次。)


以下是模板题:


[USACO06NOV] Bad Hair Day

(试题来源:Link link

Description

Some of Farmer John's \(N\) cows (\(1 ≤ N ≤ 80,000\)) are having a bad hair day! Since each cow is self-conscious about her messy hairstyle, FJ wants to count the number of other cows that can see the top of other cows' heads.

Each cow \(i\) has a specified height \(h_i\) (\(1 ≤ h_i ≤ 1,000,000,000\)) and is standing in a line of cows all facing east (to the right in our diagrams). Therefore, cow \(i\) can see the tops of the heads of cows in front of her (namely cows \(i+1\), \(i+2\), and so on), for as long as these cows are strictly shorter than cow \(i\).

Consider this example:

        =
=       =
=   -   =         Cows facing right -->
=   =   =
= - = = =
= = = = = =
1 2 3 4 5 6 

Cow#1 can see the hairstyle of cows #2, 3, 4

Cow#2 can see no cow's hairstyle

Cow#3 can see the hairstyle of cow #4

Cow#4 can see no cow's hairstyle

Cow#5 can see the hairstyle of cow 6

Cow#6 can see no cows at all!

Let \(c_i\) denote the number of cows whose hairstyle is visible from cow \(i\); please compute the sum of \(c_1\) through \(c_N\). For this example, the desired is answer \(3 + 0 + 1 + 0 + 1 + 0 = 5\).

Input

Line \(1\): The number of cows, \(N\).

Lines \(2..N+1\): Line \(i+1\) contains a single integer that is the height of cow \(i\).

Output

Line \(1\): A single integer that is the sum of \(c_1\) through \(c_N\).

Sample Input
6
10
3
7
4
12
2
Sample Output
5


单调递增栈。当原栈顶元素被踢出栈,说明原栈顶元素的右边存在更大的元素(也就是 \(i\)),此时统计答案。新建一个超大元素,用于在最后把所有栈内剩余元素踢出。

/* [USACO06NOV] Bad Hair Day
 * Au: GG
 */
#include <cstdio>
const int N=80003, inf=1e9+3;
int n, cow[N]; long long ans;
int s[N], t;

int main() {
    scanf("%d", &n);
    for (int i=1; i<=n; ++i) scanf("%d", &cow[i]);
    cow[n+1]=inf;
    for (int i=1; i<=n+1; ++i) {
        if (t && cow[i]>=cow[s[t]])
            while (t && cow[i]>=cow[s[t]])
                ans += i-s[t]-1, --t;
        s[++t]=i;
    }
    printf("%lld\n", ans);
    return 0;
}


单调队列

我们只需要维护对头(最值)元素,所以其他对答案无贡献的元素可以直接删去。

对于一个单调递增队列,维护队头、队尾,队尾元素只要大于新添加的元素一律删去。

单调递减队列同理。

在决策集合中及时排除一定不是最优解的选择,保持高度有效性和秩序性。

时间复杂度 \(O(n)\)。(每个元素至多入队一次,出队一次。)


模板题可参考 http://www.cnblogs.com/greyqz/p/9521630.html



转载于:https://www.cnblogs.com/greyqz/p/9536639.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值