• Codeforces Round #622 (Div. 2).C2


    第二次写题解,请多多指教!

    http://codeforces.com/contest/1313/problem/C2 题目链接

    不同于简单版本的暴力法,这个数据范围扩充到了五十万。所以考虑用单调栈的做法;

    1.首先顺序逆序扫一遍,记录下每个点左边的最大高度和以及右边的最大高度和 存在l[i] r[i] 两个数组中;

    2.第二步从前往后扫一边两个数组 ,得出每个点左右两边的最大高度和 l[i]+r[i]-a[i]; 以此找出最优的制高点,并标记其位置;

    3.从制高点出发,向两边求高度。反向时,每个点的最终高度应满足 a[i]=min(a[i],a[i+1]);正向时,每个点的最终高度 a[i]=min(a[i],a[i-1]);

    最后输出最终数组即可;

    上代码

    #include<bits/stdc++.h>
    using namespace std;
    long long a[500005],l[500005],r[500005];
    int main()
    {
        stack<int>st;
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        for(int i=1;i<=n;i++)
        {
            while(!st.empty()&&a[st.top()]>=a[i]) st.pop();
            if(st.empty()) l[i]=i*a[i];
            else l[i]=l[st.top()]+a[i]*(i-st.top());
            st.push(i);
        }
        while (!st.empty()) st.pop();
        for(int i=n;i>=1;i--)
        {
            while(!st.empty()&&a[st.top()]>=a[i]) st.pop();
            if(st.empty()) r[i]=(n-i+1)*a[i];
            else r[i]=r[st.top()]+a[i]*(st.top()-i);
            st.push(i); 
        }
        long long zuigao=0,idex;
        for(int i=1;i<=n;i++)
        {
            if(r[i]+l[i]-a[i]>zuigao)
            {
                zuigao=r[i]+l[i]-a[i];
                idex=i;
            }
        }
        for(int i=idex-1;i>=1;i--)
        {
            a[i]=min(a[i+1],a[i]);
        }
        for(int i=idex+1;i<=n;i++)
        {
            a[i]=min(a[i-1],a[i]);
        }
        for(int i=1;i<=n;i++) cout<<a[i]<<" ";
     } 

    最后,简单说一下简单版本的做法,即省去前面的左右扫描的步骤。直接假设每个点为最高点枚举即可。较为简单不再赘述。

    rush!
  • 相关阅读:
    mysql for update 高并发 死锁研究
    IntelliJ IDEA导航特性Top20
    idea工具
    图片水印处理-temp
    idea常用快捷键列表
    编写MyLayer,2 锚点,3 精灵的创建,4 zorder
    CSS学习(十六)-HSLA颜色模式
    android中LocalBroadcastManager的使用
    什么是鸭子类型(duck typing)
    线程应用的场景
  • 原文地址:https://www.cnblogs.com/LH2000/p/12376872.html
Copyright © 2020-2023  润新知