1308 音乐会的等待/诺诺的队列 单调栈 题解

题目地址:FJSDFZOJ 1308 音乐会的等待

对于l和r,如果[l, r]内没有大于min(l,r)的数,则这两个数可以互相看见。
求能互相看见的对数

标程对题意的理解比较奇怪。
特别要注意以下三个case:

7 
2 4 1 2 2 5 1 
8 
2 4 1 2 2 5 5 1 
9 
2 4 1 2 2 2 5 5 1 

题解:
[SMOJ2116]诺诺的队列
音乐会的等待(诺诺的队列)

系统学习单调栈和单调队列戳:单调队列和单调栈详解
https://endlesslethe.com/monotone-queue-and-stack-tutorial.html

AC代码:

#include <bits/stdc++.h>
using namespace::std;

typedef long long ll;
const int MAXN = 500000+50;
struct M {
    ll x; ll len;
} x[MAXN];

stack <M> ms;
ll cnt, n;

int main() {
    ios_base::sync_with_stdio(0);cin.tie(0);
    #ifdef LOCAL
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
    #endif
    while (scanf("%d", &n) == 1) {
        cnt = 0;
        while (!ms.empty()) ms.pop();
        for (ll i = 0; i < n; i++) {
            scanf("%d", &x[i].x);
            x[i].len = 1;
            M tmp = x[i];
            while (!ms.empty() && ms.top().x < x[i].x) {
                cnt += ms.top().len;
                ms.pop();
            }

            if (!ms.empty() && ms.top().x == x[i].x) {
                cnt += ms.top().len;
                tmp.len = ms.top().len + 1;
                ms.pop();
            }
            if (!ms.empty()) cnt++;

            ms.push(tmp);
        }
        printf("%lld\n", cnt);
    }
    return 0;
}
点赞