好久没写博客了、、、水一篇
World of Darkraft: Battle for Azathoth
题目链接:https://codeforces.com/contest/1320/problem/C
题意:
有N个武器,每个武器有它的价格;有M个盾牌,每个盾牌有它的价格
有K个怪物,每个怪物的攻击力为 X , 防御力为 Y , 杀死怪后掉落的金币为 Z
如果我们挑选的武器攻击力大于Xi,并且我们挑选的盾牌防御力大于Yi,则我们可以获得Zi个金币
要求我们必从中挑选一个武器和一个盾牌,使我们可获得的总收益最大
分析:
假设我们选择的武器为 A(价格为CA), 盾牌为 B(价格为CB)
而我们可以获得的利润为我们可以杀死的怪物们掉落的金币总和 - 武器价格 - 盾牌价格
即 ans = 可获得金币和 - CA - CB
一、预处理过程:
①、对武器排序,然后再枚举武器
②、让怪物按照X排序
③、权值线段树:
下标为防御值,即[L , R]表示[防御值为L,防御值R]
下标对应的值为金币,即tree[L] = 10 表示当盾牌防御力为L时可以获得的金币和为10
同样我们开个a数组,其中a[i]表示攻击力为i的武器的价格
过程开始之前,我们的武器已排序,怪物也已按 X 排序,我们用C数组表示怪物的属性值
我们用双指针< i , j >来进行过程 —— i 表示武器 , j 表示怪物
二、算答案过程:
①、我们枚举到i了,我们判断j这个怪物的攻击力是否小于i
②、如果小于i(c[j].x < i),那么如果我们选的盾牌防御力大于c[j].y,我们获得的金币是不是就可以加上c[j].z?
也就是说,我们当前的武器是 i ,而某一盾牌防御力只要大于c[j].y,该盾牌可获得的金币和就可以算上c[j].z
③、当然因为购买盾牌也是要money的,所以我们购买的盾牌应该为max(该盾牌可获得的金币和 - 该盾牌的价格),即最大收益
①②③对应的代码为
for(int i = 1 ; i <= n ; i ++) { while(j <= k && c[j].x < i) { //表示防御力大于c[j].y的盾牌 可获得的总收益都可以算上c[j].z update_range(c[j].y + 1 , n , c[pos].z) j ++; } ans = max(ans, tree[1].maxn - a[i]); }
有些细节就不多说了(实在太懒 -。-
#include <bits/stdc++.h> #define rep(i, a, n) for (int i = a; i <= n; i++) #define per(i, n, a) for (int i = n; i >= a; i--) #define ll long long #define int long long using namespace std; const ll INF(0x3f3f3f3f3f3f3f3fll); const int inf(0x3f3f3f3f); const int N = 1e6 + 150; int a[N], b[N], n, m, k, tot, mi1 = INF, mi2 = INF; struct Tree { ll l, r, lazy, maxn; } tree[N << 2]; void push_up(ll rt) { tree[rt].maxn = max(tree[rt << 1].maxn, tree[rt << 1 | 1].maxn); } void push_down(ll rt, ll length) { if (tree[rt].lazy) { tree[rt << 1].lazy += tree[rt].lazy; tree[rt << 1 | 1].lazy += tree[rt].lazy; tree[rt << 1].maxn += tree[rt].lazy; tree[rt << 1 | 1].maxn += tree[rt].lazy; tree[rt].lazy = 0; } } void build(ll l, ll r, ll rt) { tree[rt].lazy = 0, tree[rt].l = l, tree[rt].r = r; if (l == r) { tree[rt].maxn = -b[l]; return; } ll mid = (l + r) >> 1; build(l, mid, rt << 1); build(mid + 1, r, rt << 1 | 1); push_up(rt); } void update_range(ll L, ll R, ll key, ll rt) { if (tree[rt].r < L || tree[rt].l > R) return; if (L <= tree[rt].l && R >= tree[rt].r) { tree[rt].maxn += key; tree[rt].lazy += key; return; } push_down(rt, tree[rt].r - tree[rt].l + 1); ll mid = (tree[rt].r + tree[rt].l) >> 1; if (L <= mid) update_range(L, R, key, rt << 1); if (R > mid) update_range(L, R, key, rt << 1 | 1); push_up(rt); } struct node{ int x, y, z; bool operator<(const node &a) const{ return x < a.x; } } c[N]; signed main() { scanf("%lld %lld %lld", &n, &m, &k); rep(i, 1, n) { int pos, val; scanf("%lld %lld", &pos, &val); if (!a[pos]) a[pos] = val; else a[pos] = min(a[pos], val); mi1 = min(mi1, val), tot = max(tot, pos); } rep(i, 1, m) { int pos, val; scanf("%lld %lld", &pos, &val); if (!b[pos]) b[pos] = val; else b[pos] = min(b[pos], val); mi2 = min(mi2, val); } n = 0; per(i, N - 10, 1) { if (!b[i]) b[i] = b[i + 1]; else if (b[i + 1]) b[i] = min(b[i], b[i + 1]); if (b[i] && !n) n = i; } rep(i, 1, k) scanf("%lld %lld %lld", &c[i].x, &c[i].y, &c[i].z); sort(c + 1, c + 1 + k); int ans = -mi1 - mi2, j = 1; build(1, n, 1); rep(i, 1, tot) { if (a[i]) { while (j <= k && c[j].x < i) { update_range(c[j].y + 1, n, c[j].z, 1); j++; } ans = max(ans, tree[1].maxn - a[i]); } } printf("%lld ", ans); return 0; }