• 发射站(单调队列)


    题意

    某地有 (N) 个能量发射站排成一行,每个发射站 (i) 都有不相同的高度 (H_i),并能向两边(当然两端的只能向一边)同时发射能量值为 (V_i) 的能量,并且发出的能量只被两边最近的且比它高的发射站接收。

    显然,每个发射站发来的能量有可能被 (0)(1)(2) 个其他发射站所接受,出于安全考虑,每个发射站接收到的能量总和是我们很关心的问题。

    由于数据很多,现在只需要你帮忙计算出接收最多能量的发射站接收的能量是多少。

    数据范围

    (1 leq N leq 1000000)

    思路

    因为是向两边发射能量,因此我们可以考虑将两个方向分开考虑。因为两个方向等价,所以我们只考虑向左发射的情形。

    遍历序列中的每一个发射站,考虑它能接收到谁发出的能量。

    因为本题肯定要采取(O(n))复杂度的算法,因此先对过程进行分析,寻求有用的性质。

    考虑相邻两个发射站(i, i + 1),如果(H_i < H_{i + 1}),则(i)号发射站就不能接收到之后的能量了。

    根据这条单调性,可以考虑使用单调队列。如果当前发射站的高度大于队尾发射站的高度,就将队尾发射站出队。这样队列中维护的就是高度递减的发射站序列。

    再考虑如何更新答案,队列中的第(i)个发射站,只能将能量传给(i-1)个发射站,因此每次入队的时候更新一下前一个的接收能量总和即可。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 1000010;
    
    int n;
    int h[N], v[N];
    int sum[N];
    int q[N];
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++) scanf("%d%d", &h[i], &v[i]);
        int tt = 0, hh = 0;
        for(int i = 1; i <= n; i ++) {
            while(tt > hh && h[q[tt]] < h[i]) tt --;
            q[++ tt] = i;
            if(tt > 1) sum[q[tt - 1]] += v[q[tt]];
        }
        tt = 0; hh = 0;
        for(int i = n; i >= 1; i --) {
            while(tt > hh && h[q[tt]] < h[i]) tt --;
            q[++ tt] = i;
            if(tt > 1) sum[q[tt - 1]] += v[q[tt]];
        }
        int res = 0;
        for(int i = 1; i <= n; i ++) res = max(res, sum[i]);
        printf("%d
    ", res);
        return 0;
    }
    
  • 相关阅读:
    每日英语:Here's Why You Won't Finish This Article
    每日英语:'Still Out Of Work?' How To Handle Holiday Small Talk
    每日英语:How to Spend Christmas in Asia
    每日英语:Losing It at the Movies: Silly Beats Sober in China's Box Office
    每日英语:How Do iPhone Photos Impact Our Experience?
    一种使用CSS固定表头和列的方法
    一个asp.net中使用的flash展示控件
    gridview中cell的选择和编辑
    asp.net 2.0中的profile对象简介
    gridview中使用方向键标记选中行
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/14459067.html
Copyright © 2020-2023  润新知