CF1321E World of Darkraft: Battle for Azathoth

题面

把所有的攻击装备按攻击值排序,所有的防御装备按防御值排序,所有的怪兽按防御值排序

然后一次考虑每件攻击装备i:

由于攻击装备和怪兽分别按攻击值和防御值排序,满足第一个条件(攻击装备的攻击值大于怪兽的防御值)的怪兽下标的范围1——j一定单调增大(j单调递增)

对于所有选取攻击装备i的方案,1——j的怪兽能否击败只取决于选取的防御装备k的防御值

对防御装备建立线段树,线段树节点保存选取区间内防御装备带来的最大收益,初始值为每件防御装备的价格的相反数

用1——j的怪兽更新线段树:找到能满足第二个条件(防御值大于怪兽攻击值)的最小的k,此时第k——m件装备均可满足要求,区间加上怪兽的价值

然后用线段树根节点的值(1——m的最大值)-第i件攻击装备的价格更新答案

总结:将三个序列都有序化的好处在于是范围单调上升(即对于每个j只需修改1次),且每次修改的范围为一段区间(可用线段树维护)

#include <bits/stdc++.h>
using namespace std;
#define int long long
inline void read (int &x) {
    char ch = getchar(); x = 0;
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
} const int N = 2e5 + 5;
int n, m, p, res = -1e12, c[N << 2], tag[N << 2], q[N];
pair<int, int> a[N], b[N];
pair<int, pair<int, int> > t[N];
#define fi first
#define se second
#define ls (p << 1)
#define rs (p << 1 | 1)
#define Max(a, b) (a < b ? b : a)
void build (int p, int l, int r) {
    if (l == r) { c[p] = -b[l].se; return; } int mid (l + r >> 1);
    build (ls, l, mid), build (rs, mid + 1, r), c[p] = Max (c[ls], c[rs]);
}
inline void push_down (int p) {
    tag[ls] += tag[p], tag[rs] +=tag[p];
    c[ls] += tag[p], c[rs] +=tag[p], tag[p] = 0;
}
void modify (int p, int l, int r, int ql, int qr, int val) {
    if (ql <= l && qr >= r) { c[p] += val, tag[p] += val; return; }
    int mid (l + r >> 1); push_down (p);
    if (ql <= mid) modify (ls, l, mid, ql, qr, val);
    if (qr > mid) modify (rs, mid + 1, r, ql, qr, val);
    c[p] = Max (c[ls], c[rs]);
}
inline void update (int p) {
    int tmp = upper_bound (q + 1, q + m + 1, t[p].se.fi) - q;
//    printf ("%d %d %d\n", p, t[p].se.fi, tmp);
    if (tmp <= m) modify (1, 1, m, tmp, m, t[p].se.se);
}
signed main() {
    read (n), read (m), read (p); int j = 1;
    for (int i = 1; i <= n; ++i) read (a[i].fi), read (a[i].se);
    for (int i = 1; i <= m; ++i) read (b[i].fi), read (b[i].se);
    for (int i = 1; i <= p; ++i) read (t[i].fi), read (t[i].se.fi), read (t[i].se.se);
    sort (a + 1, a + n + 1), sort (b + 1, b + m + 1), sort (t + 1, t + p + 1);
    for (int i = 1; i <= m; ++i) q[i] = b[i].fi; build (1, 1, m);
    for (int i = 1; i <= n; ++i) {
        while (j <= p && t[j].fi < a[i].fi) update (j++);
    //    printf ("%d %d\n", j, c[1]);
        res = Max (res, c[1] - a[i].se);
    } return printf ("%lld\n", res), 0;
}

猜你喜欢

转载自www.cnblogs.com/whx666/p/12674934.html