cf1320 C. World of Darkraft: Battle for Azathoth(线段树)

题意:

有n1个武器(wea),每个武器有攻击(v)和价格(c);有n2个防具(arm),每个防具有防御(v)和价格(c);有n3个怪兽(mon),每个怪兽有防御(def)、攻击(atk)和击杀奖励(coin)。必须购买一个武器和一个防具,只有当武器的攻击大于怪的防御且防具的防御大于怪的攻击时才能击败怪兽。求最多能赚多少。

n1,n2,n3 <= 2e5,v,def,atk <= 1e6,c <= 1e9,coin <= 1e3

思路:

武器按攻击排序。对每个武器,把能被这个武器击败的怪兽加入集合,看现在达到多少防御能赚的钱最多。

处理出达到 \(b_i\) 防御的最小花费 \(b_i\)。叶子节点 \(l=r\) 记录达到 \(l\) 防御能赚多少钱,线段树维护区间最大值即可。若新加入的怪的攻击为 \(x\),则区间 \([x+1,右端点]\) 中的每个数加上这个怪的击杀奖励。要写个pushdown

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5 + 5, M = 1e6 + 5;

int n1, n2, n3;
int mb, b[M]; //最大可能防御,获得i防御的最小花费
ll ans = -2e9;
struct node1 {
    int v, c;
    bool operator< (const node1 &t) const {
        return v < t.v;
    }
} wea[N], arm[N]; //武器、防具;
struct node2 {
    int def, atk, coin;
    bool operator< (const node2 &t) const {
        return def < t.def;
    }
} mon[N]; //怪,防/攻/奖励

struct node {
    int l, r; ll MAX, lazy;
} tr[M*4];
void pushup(int u)
{
    tr[u].MAX = max(tr[u<<1].MAX, tr[u<<1|1].MAX);
}
void pushdown(int u)
{
    node &root = tr[u], &left = tr[u<<1], &right = tr[u<<1|1];
    if(root.lazy)
    {
        left.lazy += root.lazy, right.lazy += root.lazy;
        left.MAX += root.lazy, right.MAX += root.lazy;
        root.lazy = 0;
    }
}
void build(int u, int l, int r)
{
    if(l == r) tr[u] = {l, r, -b[l]};
    else
    {
        tr[u] = {l, r};
        int mid = l + r >> 1;
        build(u<<1, l, mid), build(u<<1|1, mid+1, r);
        pushup(u);
    }
}
void modify(int u, int l, int r, int d)
{
    if(tr[u].l >= l && tr[u].r <= r)
        tr[u].lazy += d, tr[u].MAX += d;
    else
    {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if(l <= mid) modify(u<<1, l, r, d);
        if(r > mid) modify(u<<1|1, l, r, d);
        pushup(u);
    }
}

signed main()
{
    memset(b, 0x3f, sizeof b);

    scanf("%d%d%d", &n1, &n2, &n3);
    for(int i = 1; i <= n1; i++) scanf("%d%d", &wea[i].v, &wea[i].c);
    for(int i = 1; i <= n2; i++) {
        scanf("%d%d", &arm[i].v, &arm[i].c); mb = max(mb, arm[i].v);
        b[arm[i].v] = min(b[arm[i].v], arm[i].c);
    }
    for(int i = 1; i <= n3; i++) scanf("%d%d%d", &mon[i].def, &mon[i].atk, &mon[i].coin);

    for(int i = mb - 1; i; i--) b[i] = min(b[i+1], b[i]);
    build(1, 1, mb);

    sort(wea + 1, wea + 1 + n1), sort(mon + 1, mon + 1 + n3);

    for(int i = 1, j = 1; i <= n1; i++) {
        for(; j <= n3 && mon[j].def < wea[i].v; j++)
            if(mon[j].atk < mb) modify(1, mon[j].atk + 1, mb, mon[j].coin);
        ans = max(ans, -wea[i].c + tr[1].MAX);
    }

    printf("%lld", ans);

    return 0;
}

posted @ 2021-12-31 14:17  Bellala  阅读(62)  评论(0)    收藏  举报