[单调栈] GYM-103185E Excellent Views

题目大意

N(N105) 个建筑排成一列,第 i 个建筑的高度是 HiHi 两两不同,从建筑 i 到建筑 j 被认为是可达的,当且仅当不存在 k 使得 |ik||ij| 并且 Hj<Hk

题解

考虑算每个 Hi 带来的贡献。维护一个从栈底到栈顶单调递减的单调栈,从左到右扫描 Hi,将 Hi 入栈。在入栈时算新入栈的 Hi 对左边的贡献,出栈时对弹出的 HjHj 对其右边带来的贡献。假设将小于 Hi 的元素都出栈后,当前栈顶是 Hj,因为 Hj>Hi,所以 Hi 会对 [j+1,i1] 的右半区间的位置都带来 1 的贡献。假设当前为了入栈 Hi,弹出了 Hj,因为 Hj<Hi,所以 Hj 会对 [j+1,i1] 的左半段区间都带来 1 的贡献。注意考虑一下边界情况。区间加用差分维护即可,时间复杂度 O(n)

Code

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

#define LL long long

template<typename elemType>
inline void Read(elemType& T) {
    elemType X = 0, w = 0; char ch = 0;
    while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    T = (w ? -X : X);
}

int a[100010], s[100010], ans[100010];
int n;

int main() {
    Read(n);
    for (int i = 1; i <= n; ++i)
        Read(a[i]);
    int top = 0;
    s[++top] = 1;
    for (int i = 2; i <= n; ++i) {
        while (top && a[s[top]] <= a[i]) {
            int L = s[top] + 1, R = i - 1;
            if (L <= R) {
                int mid = (L + R) >> 1;
                if ((R - L + 1) % 2 == 1) { ++ans[L]; --ans[mid]; }
                else { ++ans[L]; --ans[mid + 1]; }
            }
            --top;
        }
        int L = s[top] + 1, R = i - 1;
        int mid = (L + R) >> 1;
        if (L <= R) {
            if (!top) { ++ans[L]; --ans[R + 1]; }
            else { ++ans[mid + 1]; --ans[R + 1]; }
        }
        s[++top] = i;
    }
    while (top) {
        int L = s[top] + 1, R = n;
        if (L <= R) { ++ans[L]; --ans[R + 1]; }
        --top;
    }
    for (int i = 1; i <= n; ++i)
        ans[i] += ans[i - 1];
    for (int i = 1; i <= n; ++i)
        printf("%d ", ans[i]);
    printf("\n");

    return 0;
}
posted @   AE酱  阅读(59)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示