Codeforce brush questions (4)

CodeForces 1320C World of Darkraft: Battle for Azathoth

\ (n \) weapons \ (m \) shields, both weapons and shields have corresponding attack value (defense value) and price, and there are \ (p \) monsters, each monster has defense Value, attack value, and how much money you can get by killing it. You can only choose one weapon and one shield, and ask how much money you will get the most through the fight (after subtracting the cost of buying weapons and shields)?

answer

The simplest idea is \ (O (nmp) \) , obviously not. How do you start? If only one dimension is considered, after sorting weapons and monsters separately, the suffix of two points can be solved. Now it's one-dimensional: the attacks of shields and monsters are a bit difficult. For each weapon, if the monster collection it can kill (only the weapon's attack value is greater than the monster's defense value) is \ (S \) , then how to find the maximum gain in the collection \ (S \) ? ? Build a line segment tree to maintain the maximum return of the set \ (S \) . For every monster added, if its attack value is \ (x \) , then update the maximum value of the part larger than \ (x \) value. For example: let the shield with \ (a [i]: = \) defense value of \ (i \) in set S help you get the most benefit, add a monster with attack value of \ (x \) , Just update: \ (a [x + 1] + = coins, a [x + 2] + = coins, ··· \) , and then take their maximum value \ (max (a) \) is the set \ (S \) The biggest gain.

When the shield defense values are the same, and certainly less expensive option that shield, which is in the achievements of function: ma[root] = max(ma[root], -b.price).

struct monster {
    int x, y, z;
    bool operator < (const monster o) const {
        return x < o.x;
    }
};

int n, m, p, cnt;
long long ma[1000005 * 4], laz[1000005 * 4];

void Build_Tree(int l, int r, int root, int pos, int x) {
    if ((l == r) && (l == pos)) {
        ma[root] = max(ma[root], (long long)-x);  // 坑点1
        return;
    }
    int mid = (l + r) >> 1;
    if (pos <= mid) Build_Tree(l, mid, root << 1, pos, x);
    else Build_Tree(mid + 1, r, (root << 1) + 1, pos, x);
    ma[root] = max(ma[root << 1], ma[(root << 1) + 1]);
}

void Push_down(int root) {
    laz[root << 1] += laz[root];
    laz[(root << 1) + 1] += laz[root];
    ma[(root << 1)] += laz[root];
    ma[(root << 1) + 1] += laz[root];
    laz[root] = 0;
}

void Update_Tree(int L, int R, int l, int r, int root, int coins) {
    if (L > R) return;         // 坑点2
    if (L <= l && r <= R) {
        ma[root] += coins;
        laz[root] += coins;
        return;
    }
    if (laz[root]) Push_down(root);
    int mid = (l + r) >> 1;
    if (L <= mid) Update_Tree(L, R, l, mid, root << 1, coins);
    if (R > mid) Update_Tree(L, R, mid  + 1, r, (root << 1) + 1, coins);
    ma[root] = max(ma[root << 1], ma[(root << 1) + 1]);
}

int main()
{

    scanf("%d %d %d", &n, &m, &p);

    vector<pair<int, int> > a(n), b(m);
    vector<struct monster > c(p);

    int length = 0;

    myfor(i, 0, n) scanf("%d %d", &a[i].first, &a[i].second);
    myfor(i, 0, m) scanf("%d %d", &b[i].first, &b[i].second), length = max(length, b[i].first);
    myfor(i, 0, p) scanf("%d %d %d", &c[i].x, &c[i].y, &c[i].z), length = max(length, c[i].y);


    sort(a.begin(), a.end());
    sort(c.begin(), c.end());

    myfor(i, 0, length * 4) ma[i] = -INF;
    myfor(i, 0, m) Build_Tree(1, length, 1, b[i].first, b[i].second);

    int index = 0;
    long long ans = -INF;

    myfor(i, 0, n) {
        while(index < p && c[index].x < a[i].first) {
            Update_Tree(c[index].y + 1, length, 1, length, 1, c[index].z);        // length = max(c.y), 所以可能会出现:c[index].y + 1 > length 
            index++;
        }
        ans = max(ans, ma[1] - a[i].second);
    }

    cout << ans << endl;
    return 0;
}

Guess you like

Origin www.cnblogs.com/zgglj-com/p/12676739.html