zoukankan      html  css  js  c++  java
  • [CF1483C] Skyline Photo

    [CF1483C] Skyline Photo - dp,线段树,单调栈

    Description

    (n) 栋楼房,每栋楼有一个高度 (a_i) 和美丽值 (b_i)
    现在,你需要把这 (n) 栋楼房划分成若干个连续段,每一个连续段的美丽值为该段中最矮的楼房的美丽值。总的划分美丽值为每个连续段的美丽值之和。

    你需要求出最大可能的总划分美丽值。

    Solution

    分段问题,设 (f[i]) 表示处理了前 (i) 个位置的最大答案,则 (f[i]=max_{j<i} (f[j]+g(j+1,i)))

    整个东西可以用以 j 为下标的线段树维护,更新 f 的时候单点修改,更新 g 的时候是区间修改,需要用一个单调栈辅助

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    int val[1220005], tag[1220005];
    
    struct SegmentTree
    {
        int n;
        SegmentTree(int n) : n(n)
        {
        }
        void pushup(int p)
        {
            val[p] = max(val[p * 2], val[p * 2 + 1]);
        }
        void put(int p, int v)
        {
            val[p] += v;
            tag[p] += v;
        }
        void pushdown(int p, int l, int r)
        {
            if (tag[p])
            {
                put(p * 2, tag[p]);
                put(p * 2 + 1, tag[p]);
                tag[p] = 0;
            }
        }
        void modify(int p, int l, int r, int ql, int qr, int v)
        {
            if (l > qr || r < ql)
                return;
            if (l >= ql && r <= qr)
            {
                put(p, v);
                return;
            }
            pushdown(p, l, r);
            modify(p * 2, l, (l + r) / 2, ql, qr, v);
            modify(p * 2 + 1, (l + r) / 2 + 1, r, ql, qr, v);
            pushup(p);
        }
        void Modify(int ql, int qr, int v)
        {
            modify(1, 1, n, ql + 1, qr + 1, v);
        }
        int query(int p, int l, int r, int ql, int qr)
        {
            if (l > qr || r < ql)
                return -1e18;
            if (l >= ql && r <= qr)
                return val[p];
            pushdown(p, l, r);
            return max(query(p * 2, l, (l + r) / 2, ql, qr), query(p * 2 + 1, (l + r) / 2 + 1, r, ql, qr));
        }
        int Query(int ql, int qr)
        {
            return query(1, 1, n, ql + 1, qr + 1);
        }
    };
    
    signed main()
    {
        int n;
        cin >> n;
        SegmentTree seg(n + 2);
        vector<int> h(n + 2), b(n + 2);
        for (int i = 1; i <= n; i++)
            cin >> h[i];
        for (int i = 1; i <= n; i++)
            cin >> b[i];
        stack<int> sta;
        sta.push(0);
        seg.Modify(0, 0, -1e18);
        for (int i = 1; i <= n; i++)
        {
            while (h[sta.top()] > h[i])
            {
                int statop = sta.top();
                sta.pop();
                int subtop = sta.top();
                seg.Modify(subtop + 1, statop, -b[statop]);
            }
            int subtop = sta.top();
            sta.push(i);
            int statop = sta.top();
            seg.Modify(subtop + 1, statop, b[statop]);
            int f = seg.Query(0, i);
            if (i == n)
                cout << f << endl;
            seg.Modify(i + 1, i + 1, f);
        }
    }
    
  • 相关阅读:
    字符串排序算法总结
    子字符串匹配常用算法总结
    springboot拦截器
    springboot 双 sqlite 数据源配置
    myeclipse springboot 配置帆软报表
    保存在session中的登陆信息无故丢失的解决办法
    删除多条商品
    前台验证邮箱不能重复
    mybatis两张表关联关系映射
    蚂蚁金服支付平台代码配置
  • 原文地址:https://www.cnblogs.com/mollnn/p/14565260.html
Copyright © 2011-2022 走看看