[SOJ612/300iq Contest 1]约会【Hall定理】

题意简述:\(\text{_}\color{red}{\text{violet}}\)可以在接下来的\(t\)天和\(n\)个纸片人小姐姐约会,其中第\(i\)个纸片人小姐姐只能在第\([l_i, r_i]\)天内约会至多一次,并给\(\text{_}\color{red}{\text{violet}}\)带来\(p_i\)的愉悦度。\(\text{_}\color{red}{\text{violet}}\)在第\(i\)天有\(a_i\)次机会和纸片人小姐姐约会,求\(t\)天内最大的愉悦度。\(1\leq n, t \leq 3\times 10^5\),且\(\forall i \in [1, n), l_i\leq l_{i+1}, r_i\leq r_{i+1}\)


#include <cstdio>
#include <cctype>
#include <cstring>
#include <cassert>
#include <iostream>
#include <algorithm>
#define R register
#define ll long long
using namespace std;
const int N = 310000, K = N << 2;
const ll inf = 1e18;

int n, m, lt[K], rt[K], lg[N], rg[N], maxT[K], minT[K];
ll a[N], maxV[K], minV[K], ans;
struct node {
    int p, ind;
    inline bool operator < (const node &x) const {
        return p > x.p;
    }
}g[N];
inline void pushdown(int);

template <class T> inline void read(T &x) {
    x = 0;
    char ch = getchar(), w = 0;
    while (!isdigit(ch)) w = (ch == '-'), ch = getchar();
    while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
    x = w ? -x : x;
    return;
}

void build(int k) {
    if (lt[k] == rt[k]) {
        minV[k] = -a[lg[lt[k]] - 1], maxV[k] = -a[rg[rt[k]]];
        return;
    }
    int mid = (lt[k] + rt[k]) >> 1, l = k << 1, r = (k << 1) + 1;
    lt[l] = lt[k], rt[l] = mid, lt[r] = mid + 1, rt[r] = rt[k];
    build(l), build(r);
    minV[k] = min(minV[l], minV[r]), maxV[k] = max(maxV[l], maxV[r]);
    return;
}

void modify(int k, int x, int y, int w, int opt) {
    if (y < x) return;
    if (lt[k] >= x && rt[k] <= y) {
        if (opt) maxT[k] += w, maxV[k] += w;
        else minT[k] += w, minV[k] += w;
        return;
    }
    pushdown(k);
    int mid = (lt[k] + rt[k]) >> 1, l = k << 1, r = (k << 1) + 1;
    if (x <= mid) modify(l, x, y, w, opt);
    if (y > mid) modify(r, x, y, w, opt);
    minV[k] = min(minV[l], minV[r]), maxV[k] = max(maxV[l], maxV[r]);
    return;
}

ll query(int k, int x, int y, int opt) {
    if (lt[k] >= x && rt[k] <= y)
        return opt ? maxV[k] : minV[k];
    pushdown(k);
    int mid = (lt[k] + rt[k]) >> 1, l = k << 1, r = (k << 1) + 1;
    ll ret = opt ? -inf : inf, w;
    if (x <= mid) w = query(l, x, y, opt), ret = opt ? max(ret, w) : min(ret, w);
    if (y > mid) w = query(r, x, y, opt), ret = opt ? max(ret, w) : min(ret, w);
    return ret;
}

void pushdown(int k) {
    int l = k << 1, r = (k << 1) + 1;
    if (minT[k]) {
        modify(l, lt[k], rt[k], minT[k], 0);
        modify(r, lt[k], rt[k], minT[k], 0);
        minT[k] = 0;
    }
    if (maxT[k]) {
        modify(l, lt[k], rt[k], maxT[k], 1);
        modify(r, lt[k], rt[k], maxT[k], 1);
        maxT[k] = 0;
    }
    return;
}

int main() {
    read(n), read(m);
    for (R int i = 1; i <= m; ++i)
        read(a[i]), a[i] += a[i - 1];
    for (R int i = 1; i <= n; ++i)
        read(lg[i]), read(rg[i]), read(g[i].p), g[i].ind = i;
    sort(g + 1, g + 1 + n);
    lt[1] = 1, rt[1] = n, build(1);
    for (R int i = 1; i <= n; ++i) {
        if (query(1, 1, g[i].ind, 0) <= query(1, g[i].ind, n, 1))
            continue;
        modify(1, g[i].ind + 1, n, 1, 0), modify(1, g[i].ind, n, 1, 1);
        ans += g[i].p;
    }
    cout << ans << endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/suwakow/p/11674170.html
今日推荐