CF1320C 【World of Darkraft: Battle for Azathoth】

必须买一个武器,买一个防具,然后去打怪,求最大收益。

由于武器的攻击力必须严格大于怪物的防御力,所以我们先满足每个武器的条件,然后去配一个最优收益的防具。

所以我们可以把武器案攻击力排序,怪物按防御力排序,然后枚举每一个武器时可以发现他们的大于区间是单调上升的。

既然如此,那我们不如枚举每一个怪物,然后动态更新每一款防具的收益,找到防具的最大收益即可。

但我们怎么更新每一款防具的收益呢?易知,怪物攻击力必须小于防具防御力,所以我们只需要更新那些防御力比怪物攻击力大的去更新,如果我们把防具按防御力大小排序,这就是一个区间修改问题,右端点已经确定,那我们怎么确定做端点呢?可以用二分查找第一个比它大的就行了。

下面是代码:

#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 2e5 + 5;
int n , m , p , t[MAXN << 2] , tag[MAXN << 2];
struct node2 {
	int x , y , z;
}mon[MAXN];
struct node {
	int val , cost;
	node () {}
	node (int x) {
		val = x;
	}
	bool operator < (const node x) const {
		return val < x.val;
	}
}a[MAXN] , b[MAXN];

bool cmp(node x , node y) {
	if(x.val == y.val) return x.cost < y.cost;
	return x.val < y.val;
}

bool cmp1(node2 x , node2 y) {
	return x.x < y.x;
}
void push_down(int now) {
	if(tag[now]) {
		t[now << 1] += tag[now];
		t[now << 1 | 1] += tag[now];
		tag[now << 1] += tag[now];
		tag[now << 1 | 1] += tag[now];
		tag[now] = 0;
	}
}
void build(int l , int r , int now) {
	if(l == r) {
		t[now] = -b[l].cost;
		return;
	}
	int mid = (l + r) >> 1;
	build(l , mid , now << 1);
	build(mid + 1 , r , now << 1 | 1);
	t[now] = max(t[now << 1] , t[now << 1 | 1]);
}
void update(int l , int r , int now , int x , int y , int z) {
	if(x > y) return;
	if(l >= x && r <= y) {
		t[now] += z;
		tag[now] += z;
		return;
	}
	int mid = (l + r) >> 1;
	push_down(now);
	if(x <= mid) update(l , mid , now << 1 , x , y , z);
	if(y > mid) update(mid + 1 , r , now << 1 | 1 , x , y , z);
	t[now] = max(t[now << 1] , t[now << 1 | 1]);
}
int main() {
	scanf("%d %d %d" , &n , &m , &p);
	for (int i = 1; i <= n; ++i) scanf("%d %d" , &a[i].val , &a[i].cost);
	sort(a + 1 , a + 1 + n , cmp);
	for (int i = 1; i <= m; ++i) scanf("%d %d" , &b[i].val , &b[i].cost);
	sort(b + 1 , b + 1 + m , cmp);
	build(1 , m , 1);
	for (int i = 1; i <= p; ++i) scanf("%d %d %d" , &mon[i].x , &mon[i].y , &mon[i].z);
	sort(mon + 1 , mon + 1 + p , cmp1);
	int l = 1 , ans = -2e9;
	for (int i = 1; i <= p; ++i) {
		if(mon[i].x < a[l].val) {
			int x = upper_bound(b + 1 , b + 1 + m , node(mon[i].y)) - b;
			update(1 , m , 1 , x , m , mon[i].z);
		}
		else {
			ans = max(ans , t[1] - a[l].cost);
			l ++;
			if(l > n) break;
			i --;
		}
	}
	for (int i = l; i <= n; ++i) ans = max(ans , t[1] - a[i].cost);
	printf("%d" , ans);
	return 0;
}
原文地址:https://www.cnblogs.com/Reanap/p/13423284.html