• 【题解】良好的感觉


    题目链接

    解:

    dp题目。

    先对题目分析一下:目的是让我们最大化区间中任意一段的和乘以它的最小值。

    怎么办?

    首先,据题目得知,前缀和一定是递增的,因为没有负数。

    那么,我们可以得出结论,对于任意区间的最小值x,它的区间长度越大,它的贡献就越大。

    那我们找它的右边和左边第一个小于它的值的下标就好了。

    你想到了什么?

    单调栈。

    我们让一个下标进栈。每次,当栈顶元素大于当前元素时:

    将栈顶出栈,并且栈顶的右端点就是当前的i.与此同时,将栈顶删除。

    那么,它的左端点是啥呢?

    当栈顶的元素小于当前值了,那么当前值的左端点就显然是栈顶了。

    最后,将当前下标入栈。

    还需要特判,当一个位置的左端点是空时,说明它是它以左所有区间(以它为右端点)的最小值,则将其设为0.

    反之同理。

    最后,对于每一个位置i,都对于它取MAX.

    Code:

    #include<iostream>
    #include<cstdio>
    #include<stack>
    using namespace std;
    int n,a[500000],L[500000],R[500000];
    long long f[500000],ans,sum[500000];
    long long q[500000],top;
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;++i){
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        for(int i=1;i<=n;++i){
            while(top&&a[q[top]]>=a[i])R[q[top--]]=i;
            L[i]=q[top];
            q[++top]=i;
        }
        for(int i=1;i<=n;++i){
            if(!L[i])L[i]=0;
            if(!R[i])R[i]=n;
        }
        for(int i=1;i<=n;++i)ans=max(ans,a[i]*(sum[R[i]-1]-sum[L[i]]));
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Android(java)学习笔记6:实现Runnable接口创建线程 和 使用Callable和Future创建线程
    Android(java)学习笔记5:线程的生命周期
    Android(java)学习笔记4:线程的控制
    Android(java)学习笔记3:线程的优先级
    Android(java)学习笔记2:继承Thread类创建线程类
    凑算式
    三洋献瑞
    三洋献瑞
    三洋献瑞
    移动距离
  • 原文地址:https://www.cnblogs.com/h-lka/p/11281811.html
Copyright © 2020-2023  润新知