• Bzoj 4094: [Usaco2013 Dec]Optimal Milking --SegTree


    4094: [Usaco2013 Dec]Optimal Milking

    Description

    Farmer John最近购买了N(1 <= N <= 40000)台挤奶机,编号为1 ... N,并排成一行。第i台挤奶机每天能够挤M(i
    )单位的牛奶 (1 < =M(i) <=100,000)。由于机器间距离太近,使得两台相邻的机器不能在同一天使用。Farmer Jo
    hn可以自由选择不同的机器集合在不同的日子进行挤奶。在D(1 < = D < = 50,000)天中,每天Farmer John对某一
    台挤奶机进行维护,改变该挤奶机的产量。Farmer John希望设计一个挤奶方案,使得挤奶机能够在D天后获取最多
    的牛奶。

    Input

    第1行:两个整数N和D
    第2..N+1行:每台挤奶机的M(i)
    第N+2..N+D+1行:两个整数i和m,表示每天对机器i进行维护,机器i的产量为m。

    Output

    最大产量

    Sample Input

    5 3
    1
    2
    3
    4
    5
    5 2
    2 7
    1 10

    Sample Output

    32
    【样例解释】
    第1天,最优方案为2+4=6 ( 方案1+3+2一样)
    第2天,最优方案为7+4=11
    第3天,最优方案为10+3+2=15

    思路:

      小白逛公园做过没有,一样的题,单点修改全局查询区间合并线段树裸题;

    我们设t为区间最大值, lt为强制不选最左结点的最大值, rt为强制不选右结点的最大值,d为强制不选两端点的最大值。

    pushup很好想。

    下面是代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #define ls p<<1
    #define rs p<<1|1
    using namespace std;
    const int N = 41000;
    int n, d, a[N];
    class Segment_Tree {
    public:    
        int t[N<<2], lt[N<<2], rt[N<<2], d[N<<2];
        inline void Pushup(int p) {
            t[p] = max(t[ls]+lt[rs], t[rs]+rt[ls]);
            lt[p] = max(d[ls]+t[rs], lt[ls]+lt[rs]);
            rt[p] = max(d[rs]+t[ls], rt[ls]+rt[rs]);
            d[p] = max(lt[ls]+d[rs], d[ls]+rt[rs]);
        }
    
        void Build(int l, int r, int p) {
            if(l==r) {
                t[p] = a[l];
                return ;
            }
            int mid = (l+r) >> 1;
            Build(l, mid, ls);
            Build(mid+1, r, rs);
            Pushup(p);
        }
        void Change(int l, int r, int p, int x, int c) {
            if(l==r) {
                a[l] = c;
                t[p] = c;
                return ;
            }
            int mid = (l+r) >> 1;
            if(x<=mid) Change(l, mid, ls, x, c);
            else Change(mid+1, r, rs, x, c);
            Pushup(p);
        }
    }Tr;
    long long ans = 0;
    class Init_Solve {
    public:
        void init() {
            scanf("%d%d",&n,&d);
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            Tr.Build(1, n, 1);
            for(int i=1;i<=d;i++) {
                int x, c;
                scanf("%d %d", &x, &c);
                Tr.Change(1, n, 1, x, c);
                ans+=Tr.t[1];
            }
            printf("%lld
    ",ans);
        }
    }Is;
    int main() {
        Is.init();
    }
    
  • 相关阅读:
    square(正方形)
    敌兵布阵
    Addition Chains(加法链)
    贪心算法理论
    难题,未解决
    Linux上vi(vim)编辑器使用教程
    linux下md5sum的使用
    Java读取csv文件
    S2JDBCタイプセーフAPI
    S2JDBCチュートリアル
  • 原文地址:https://www.cnblogs.com/Tobichi/p/9184685.html
Copyright © 2020-2023  润新知