zoukankan      html  css  js  c++  java
  • (牛客)区区区间间间(单调栈)

    区区区间间间

    思路

    定义(V_{l, r} = max(a_i - a _j | l <= i, j <= r))

    (sum_{l = 1} ^ {n} sum_{r = l + 1} ^ {n}V_{l, r}),转换(sum_{l = 1} ^{n} sum_{r = l + 1} ^ {n}max(a_i) - sum_{l = 1} ^{n} sum_{r = l + 1} ^ {n}min(a_i))

    因此这里就转换成了求一个区间内的最大和最小值。

    我们考虑最大值的区间覆盖,这里就形成了一个单调栈了,在当前取值的左右两侧都是递增的,因此我们得到当前值得区间覆盖,只需要左右分别进行两趟扫描,就可以得到其最左和最右的区间覆盖,分别记为(l[i],r[i])

    在这里我们还需要考虑的一点就是当存在相同的时候, 我们要选择最左还是最右来当一个最大值,这样才能保证多值相同存在的情况下我们得到的区间的合理性。这里我选择左侧的相同值更大。

    再来说一下,答案的更新,首先我们得到区间的覆盖(l[i],r[i])

    我们选定i作为区间的一个端点,可以得到((i - l[i]) + (r[i] - i) = r[i] - l[i])个区间,我们假定i在区间里,总共的区间就是((r[i] - i) * (i - l[i])),左右各取端点的排列嘛。

    然后我们需要更新的答案就是(a[i] * (r[i] - l[i] + (r[i] - i) * (i - l[i])))

    代码

    #include <bits/stdc++.h>
     
    using namespace std;
     
    typedef long long ll;
     
    const int N = 1e5 + 10;
     
    int a[N], n;
     
    ll l[N], r[N];
     
    ll get_max() {
        ll ans = 0;
        stack<int> stk;
        for(int i = 1; i <= n; i++) {
            while(!stk.empty() && a[i] >= a[stk.top()]) stk.pop();//取等号,
            if(stk.size() == 0) l[i] = 1;//栈空代表他的覆盖区域是最左点,
            else    l[i] = stk.top() + 1;
            stk.push(i);
        }
        while(!stk.empty()) stk.pop();
        for(int i = n; i >= 0; i--) {
            while(!stk.empty() && a[i] > a[stk.top()])  stk.pop();//不取等号,
            if(stk.size() == 0) r[i] = n;
            else r[i] = stk.top() - 1;
            stk.push(i);
        }
        for(int i = 1; i <= n; i++)
            ans += 1ll * (r[i] - l[i] + (i - l[i]) * (r[i] - i)) * a[i];
        return ans;
    }
     
    int main() {
        // freopen("in.txt", "r", stdin);
        int t; scanf("%d", &t);
        while(t--) {
            scanf("%d", &n);
            for(int i = 1; i <= n; i++)
                scanf("%d", &a[i]);
            ll ans = 0;
            ans += get_max();//找到最大值,
            // printf("%lld
    ", ans);
            for(int i = 1; i <= n; i++)//负数的最大,也就是未改变值时的最小,只要加上这个值就是最小值了。
                a[i] = -a[i];
            ans += get_max();
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    ArcEngine 地图与布局的联动
    ArcGIS Server安装篇
    AO+C#设置栅格图层基高 制作三维
    ArcGIS 10研究(一) 之 Desktop总体介绍 转载
    linux centos7 增加硬盘
    linux CentOS7安装oracle12c
    java中关于Socket类通信的基本测试程序
    Ubuntu 的中国梦
    我们无需“开始”菜单
    数据库战略高度解析 之系列说明
  • 原文地址:https://www.cnblogs.com/lifehappy/p/12922225.html
Copyright © 2011-2022 走看看