CF1320C - World of Darkraft: Battle for Azathoth 思维+线段树

CF1320C - World of Darkraft: Battle for Azathoth

题意

N N 个武器, M M 个防具, K K 个怪兽
每一个武器都有对应的攻击力 a i a_i ,还有购买它的金币数 c a i ca_i
每一个防具都有对应的防御力 b i b_i ,还有购买它的金币数 c b i cb_i
每一个怪兽都有对应的攻击力 x i x_i ,防御力 y i y_i ,打败他获得的金币数 z i z_i
如果现在持有武器和防具,只有在 a > x i , b > y i a>x_i,b > y_i 的情况下才能打败怪兽 i i
现在各选一件武器和防具,使得获得的收益最大

题解

偏序问题,我先想到的就是排序
将怪兽按其攻击力 x i x_i 排序
这样扫到第 i i 个怪兽的时候,如果当前武器攻击力为 x i + 1 x_i+1 的话,前面的怪兽的攻击力都是小于 x i + 1 x_i+1
这样只需要看防御力是不是大于前面的怪兽就行
换个角度来想,一只防御力为 y y 的怪兽,只会对防御力为 [ y + 1 , 1 0 6 ] [y+1,10^6] 的防具有贡献
所以这里可以用线段树来维护每一个防御力的最大收益,区间更新操作维护最大值
初始值就是每一个防御力购买防具的最小花费

代码

#include <bits/stdc++.h>
using namespace std;
#define lc  u<<1
#define rc  u<<1|1
#define mid (t[u].l+t[u].r)/2
typedef long long ll;
typedef pair<int, int> pii;
const int MAX = 1e6 + 10;
const int tot = 1e6;
const ll inf = 1e18;
int N, M, K;
ll a[MAX], b[MAX];
vector<pii> g[MAX];

struct SegmentTree {
    int l, r;
    ll mx, tag;
    void upd(ll k) {
        mx += k;
        tag += k;
    }
} t[MAX << 2];
void push_up(int u) { t[u].mx = max(t[lc].mx, t[rc].mx); }
void push_down(int u) {
    if (t[u].tag) {
        t[lc].upd(t[u].tag);
        t[rc].upd(t[u].tag);
        t[u].tag = 0;
    }
}
void build(int u, int l, int r) {
    t[u] = SegmentTree{ l, r, -inf, 0 };
    if (l == r) {
        t[u].mx = -b[l];
        return;
    }
    build(lc, l, mid);
    build(rc, mid + 1, r);
    push_up(u);
}
void update(int u, int ql, int qr, ll k) {
    if (ql <= t[u].l && t[u].r <= qr) {
        t[u].upd(k);
        return;
    }
    push_down(u);
    if (ql <= mid) update(lc, ql, qr, k);
    if (qr > mid) update(rc, ql, qr, k);
    push_up(u);
}

int main() {
    scanf("%d%d%d", &N, &M, &K);
    for (int i = 1; i < MAX; i++) a[i] = b[i] = inf;
    for (int i = 1; i <= N; i++) {
        int x, y; scanf("%d%d", &x, &y);
        a[x] = min(a[x], 1ll * y);
    }
    for (int i = 1; i <= M; i++) {
        int x, y; scanf("%d%d", &x, &y);
        b[x] = min(b[x], 1ll * y);
    }
    for (int i = 1; i <= K; i++) {
        int x, y, z; scanf("%d%d%d", &x, &y, &z);
        g[x].push_back(make_pair(y, z));
    }
    build(1, 1, tot);
    ll ans = -inf;
    for (int i = 1; i <= tot; i++) {
        ans = max(ans, t[1].mx - a[i]);
        for (pii &j: g[i])
            if (j.first + 1 <= tot)
                update(1, j.first + 1, tot, j.second);
    }
    printf("%lld\n", ans);
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44282912/article/details/104684902