最优屏障(牛客)

最优屏障

题目链接

在这里插入图片描述
在这里插入图片描述

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
const int M = 5 * 1e5 + 10;
int t, n;
int a[M];
int b[M], c[M];
struct node {
    int ln, rn;
} p[M];
void call() {
    stack<int> s;
    for (int i = 0; i < n; ++i) {
        int ans = 0;
        while (!s.empty()) {
            int k = s.top();
            if (a[i] > a[k]) {
                ans++;
                p[k].rn++;
                s.pop();
            } else {
                p[i].ln++;
                break;
            }
        }
        p[i].ln += ans;
        if (!s.empty()) {
            int k = s.top();
            p[k].rn++;
        }
        s.push(i);
    }
}
int main() {
    cin >> t;
    for (int w = 1; w <= t; ++w) {
        memset(p, 0, sizeof(p));
        scanf("%d", &n);
        for (int i = 0; i < n; ++i)
            scanf("%d", &a[i]);
        call();//求每座山可以和左边右边山分别连接的数量
        b[0] = p[0].ln, c[0] = p[0].rn;
        for (int i = 1; i < n; ++i) {//前缀和
            b[i] = b[i - 1] + p[i].ln;
            c[i] = c[i - 1] + p[i].rn;
        }
        int ans = 0, minn = 0, g = 0;
        for (int i = 1; i < n; ++i) {
            ans = c[i - 1] - b[i - 1];//求屏障之后的损失
            if (ans > minn) {
                minn = ans;
                g = i;
            }
        }

        printf("Case #%d: %d %d\n", w, g + 1, minn);
    }
    return 0;
}

题解:用call函数去求出每座山可以和左边山连接的数量,以及可以和右边山连接的数量;然后两个都做一个前缀和;之后用一个O(n)去枚举屏障的每个位置,用前缀和就可以求出做了屏障之后损失的连接,简单做个比较记录序号就可以得出结果了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值