zoukankan      html  css  js  c++  java
  • 南昌 Max answer

    https://nanti.jisuanke.com/t/38228

    Alice has a magic array. She suggests that the value of a interval is equal to the sum of the values in the interval, multiplied by the smallest value in the interval.

    Now she is planning to find the max value of the intervals in her array. Can you help her?

    Input

    First line contains an integer n(1≤n≤5×105n(1 le n le 5 imes 10 ^5n(1n5×105).

    Second line contains nnn integers represent the array a(−105≤ai≤105)a (-10^5 le a_i le 10^5)a(105ai105).

    Output

    One line contains an integer represent the answer of the array.

    样例输入

    5
    1 2 3 4 5

    样例输出

    36
    题意:求区间和乘以区间内最小的一个数的最大值,包含正负

    题解:前缀和预处理,单调栈找到每一个数向左延伸的最大距离和向右延伸的最大距离,分别记录这两个坐标。
    求最大值的时候分正负处理:
    正数:mx=max(mx,a[i]*(sum[r[i]]-sum[l[i]]+a[l[i]];
    负数:暴力加和,[l[i],r[i]]区间内的数都加起来,每次更新最小和(因为是负数,乘以a[i]后就是最大值)

    #include<iostream>
    #include<string.h>
    #include<stack>
    #define ll long long
    using namespace std;
    ll l[500005], r[500005], a[500005], sum[500005];
    ll n,mx;
    int main()
    {
        while (~scanf("%lld", &n))
        {
            for (int i = 0; i < n; i++)//刚开始是从1开始输入的,然后前缀和也是从1开始处理的,一位可以简单一点,但是因为
            {                          //栈是从0开始处理的,下面的a[p.top()]可能为a[0],导致一直TLE,找这个错误到自闭。。。
                scanf("%lld", &a[i]);
            }
            sum[0] = a[0];
            for (int i = 1; i < n; i++)
            {
                sum[i] = sum[i - 1] + a[i];
            }
            stack<ll>p;
            for (int i = 0; i < n; i++)
            {
                while (!p.empty() && a[p.top()] >= a[i])//按照大于等于a[i]的规则,从a[i]开始,向左边可以延伸最远的数的下标
                    p.pop();
                if (p.empty())//说明a[i]左边的所有数都大于等于a[i]
                    l[i] = 0;
                else//找到就记录从a[i]开始向左边寻找大于等于a[i]的最大边界下标
                    l[i] = p.top() + 1;
                p.push(i);
            }
            while (!p.empty())
                p.pop();
            for (int i = n - 1; i >= 0; i--)//往右边找第一个比a[i]小的数
            {
                while (!p.empty() && a[p.top()] >= a[i])
                    p.pop();
                if (p.empty())
                    r[i] = n - 1;
                else
                    r[i] = p.top() - 1;
                p.push(i);
            }
            mx = 0;
            for (int i = 0; i < n; i++)
            {
                if (a[i] >= 0)
                    mx = max(mx, a[i] * (sum[r[i]] - sum[l[i]] + a[l[i]]));//这里是a[l[i]]
                else
                {
                    ll ans = 0, m1 = 0, m2 = 0;
                    for (int j = i + 1; j <= r[i] && j < n; j++)
                    {
                        ans = ans + a[j];
                        m1 = min(m1, ans);
                    }
                    ans = 0;
                    for (int j = i - 1; j >= l[i] && j >= 0; j--)
                    {
                        ans = ans + a[j];
                        m2 = min(ans, m2);
                    }
                    mx = max(mx, a[i] * (m1 + m2 + a[i]));
                }
            }
    
            printf("%lld
    ", mx);
            // for(int i=1;i<=n;i++)
            //     cout<<l[i]<<' ';
            // cout<<endl;
            // for(int i=1;i<=n;i++)
            //     cout<<r[i]<<' ';
            // cout<<endl;
    
        }
        return 0;
    }
  • 相关阅读:
    法语助手2010破解
    一个很简单的例子,从汇编层次理解函数调用
    ubuntu11.10配置IPV6
    linux创建 / 删除用户及用户管理
    设置gdb反汇编语法为intel
    ubuntu server 10.04 LTS(64位)装不了花生壳的解决方法
    实现windows和linux互传文件
    在ubuntu11.10中安装chrome浏览器
    poj 1755 Triathlon 半平面交判断不等式是否有解
    poj 1474 Video Surveillance 半平面交
  • 原文地址:https://www.cnblogs.com/-citywall123/p/10792708.html
Copyright © 2011-2022 走看看