34 ACwing 295 Cleaning Shifts 题解

Cleaning Shifts

题面

农夫约翰雇佣他的 N 头奶牛帮他进行牛棚的清理工作。

他将全天分为了很多个班次,其中第 M 个班次到第 E 个班次(包括这两个班次)之间必须都有牛进行清理。

这 N 头牛中,第 i 头牛可以从第 ai 个班次工作到第 bi 个班次,同时,它会索取 ci 的佣金。

请你安排一个合理的清理班次,使得 [M,E] 时间段内都有奶牛在清理,并且所需支付给奶牛的报酬最少。

1 ≤ N ≤ 10000,
0 ≤ M,E ≤ 86399,
M ≤ ai ≤ bi ≤ E,
0 ≤ ci ≤ 500000

题解

\(f(i)\) 表示只用 \(i\) 左边的区间 \([M,i]\) 都有牛打扫的最小代价,初始 \(f(M - 1) = 0\) ,目标为 \(f(E)\)

初始先按照 \(b_i\) 从小到大排序,然后一个一个转移,保证无后效性

有转移 \(f(b_i) = \min_{a_i - 1 \le j < b_i} \{ f(j) \} + c_i\)

用线段树来维护 \(f\) ,可以在 \(O(\log n)\) 内实现区间查询最小值以及单点修改,总时间复杂度为 \(O(n \log n)\)

code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>

using namespace std;

typedef long long ll;

const int N = 1e5 + 10;
const ll INF = 4e18;


int n, L, R;
struct Cow {
    int l, r, c;
    bool operator < (const Cow &t) const {
        return r < t.r;
    }
} a[N];

struct Segment {
    #define ls (p << 1)
    #define rs (p << 1 | 1)

    ll val[N << 2];
    void update (int p) {
        val[p] = min (val[ls], val[rs]);
    }
    void build (int p, int l, int r) {
        val[p] = INF;
        if (l == r) return;
        int mid = (l + r) >> 1;
        build (ls, l, mid);
        build (rs, mid + 1, r);
    }
    void modify (int p, int l, int r, int pos, ll d) {
        if (l == r) {
            val[p] = min (val[p], d);
            return;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid) modify (ls, l, mid, pos, d);
        else modify (rs, mid + 1, r, pos, d);
        update (p);
    }
    ll query (int p, int l, int r, int x, int y) {
        if (x <= l && r <= y) {
            return val[p];
        } 
        int mid = (l + r) >> 1;
        ll res = INF;
        if (x <= mid) res = min (res, query (ls, l, mid, x, y));
        if (mid < y) res = min (res, query (rs, mid + 1, r, x, y));
        return res; 
    }

} Tr;


int main () {
    cin >> n >> L >> R;
    for (int i = 1; i <= n; i ++) {
        cin >> a[i].l >> a[i].r >> a[i].c;
    }
    sort (a + 1, a + 1 + n);

    Tr.build (1, L - 1, R);
    Tr.modify (1, L - 1, R, L - 1, 0);

    for (int i = 1; i <= n; i ++) {
        ll res = Tr.query (1, L - 1, R, a[i].l - 1, a[i].r - 1) + a[i].c;
        Tr.modify (1, L - 1, R, a[i].r, res);
    }

    ll res = Tr.query (1, L - 1, R, R, R);
    if (res == INF) cout << -1 << endl;
    else cout << res << endl;

    return 0;
}
posted @ 2025-10-05 18:15  michaele  阅读(5)  评论(0)    收藏  举报