CodeForces_1320C World of Darkraft: Battle for Azathoth(线段树)

World of Darkraft: Battle for Azathoth

time limit per test:2 seconds
memory limit per test:512 megabytes
Problem Description

Roma is playing a new expansion for his favorite game World of Darkraft. He made a new character and is going for his first grind.

Roma has a choice to buy exactly one of n different weapons and exactly one of m m m different armor sets. Weapon i i i has attack modifier a i a_i ai and is worth c a i ca_i cai coins, and armor set j j j has defense modifier b j b_j bj and is worth c b j cb_j cbj coins.

After choosing his equipment Roma can proceed to defeat some monsters. There are p p p monsters he can try to defeat. Monster k k k has defense x k x_k xk, attack y k y_k yk and possesses z k z_k zk coins. Roma can defeat a monster if his weapon’s attack modifier is larger than the monster’s defense, and his armor set’s defense modifier is larger than the monster’s attack. That is, a monster k k k can be defeated with a weapon i and an armor set j if a i > x k a_i>x_k ai>xk and b j > y k b_j>y_k bj>yk. After defeating the monster, Roma takes all the coins from them. During the grind, Roma can defeat as many monsters as he likes. Monsters do not respawn, thus each monster can be defeated at most one.

Thanks to Roma’s excessive donations, we can assume that he has an infinite amount of in-game currency and can afford any of the weapons and armor sets. Still, he wants to maximize the profit of the grind. The profit is defined as the total coins obtained from all defeated monsters minus the cost of his equipment. Note that Roma must purchase a weapon and an armor set even if he can not cover their cost with obtained coins.

Help Roma find the maximum profit of the grind.

Input

The first line contains three integers n, m, and p ( 1 ≤ n , m , p ≤ 2 ⋅ 1 0 5 1≤n,m,p≤2⋅10^5 1n,m,p2105) — the number of available weapons, armor sets and monsters respectively.

The following n lines describe available weapons. The i-th of these lines contains two integers a i a_i ai and c a i ca_i cai ( 1 ≤ a i ≤ 1 0 6 1≤a_i≤10^6 1ai106, 1 ≤ c a i ≤ 1 0 9 1≤ca_i≤10^9 1cai109) — the attack modifier and the cost of the weapon i.

The following m lines describe available armor sets. The j-th of these lines contains two integers b j b_j bj and c b j cb_j cbj ( 1 ≤ b j ≤ 1 0 6 1≤b_j≤10^6 1bj106, 1 ≤ c b j ≤ 1 0 9 1≤cb_j≤10^9 1cbj109) — the defense modifier and the cost of the armor set j.

The following p lines describe monsters. The k-th of these lines contains three integers x k x_k xk, y k y_k yk, z k z_k zk ( 1 ≤ x k , y k ≤ 1 0 6 1≤x_k,y_k≤10^6 1xk,yk106, 1 ≤ z k ≤ 1 0 3 1≤z_k≤10^3 1zk103) — defense, attack and the number of coins of the monster k.

Output

Print a single integer — the maximum profit of the grind.

Sample Input

2 3 3
2 3
4 7
2 4
3 2
5 11
1 2 4
2 1 6
3 4 6

Sample Output

1

题意

有n把武器,m件防具,p只怪物,每把武器有攻击值 a i a_i ai、价格 c a i ca_i cai;每件防具有防御值 b j b_j bj、价格 c b j cb_j cbj;怪物有防御值 x k x_k xk、攻击值 y k y_k yk、奖励 z k z_k zk。勇者可以(必须)选择购买一把武器和一件防具,当勇者的攻击值大于怪物的防御值且勇者防御值大于怪物攻击值,则勇者可以击杀这只怪物并获得其对应的奖励。勇者可以击杀多只怪物,每只怪物只能被击杀一次。求勇者能获得的最大收益(打怪奖励-武器价格-防具价格)。

题解:

线段树。可以考虑对一种属性值排序,线段树维护另一种属性值的最大收益。这里对攻击排序,然后线段树维护防御为某个值时的最大收益。初始的收益为购买防具的花费。
接下来考虑防御的变化对收益的影响,对于一个怪物,其攻击值为y,收益为z,那么所有防御值大于y的收益都可以加上z。所以可以将防御值y+1到ymaxn(最大可达的防御)的部分收益都加上z。
之后暴力枚举购买的武器,然后将所有防御低于该武器的攻击值的怪物收益加入线段树中。(因为武器攻击值有序,所以只需要加入防御大于等于上把武器,小于当前武器的怪物收益)。然后查询线段树中收益的最大值即可。
这边其实可以离散化一下,不过单属性最大1e6,不离散化应该也可以。
有点类似于二维偏序问题。

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctype.h>
#include<cstring>
#include<queue>
#include<stack>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-6
 
using namespace std;
typedef long long LL;   
typedef pair<LL, int> P;
const int maxn = 200100;
const int mod = 1000000007;
struct node{
    int a, b, p;
}atk[maxn], def[maxn], mon[maxn];
LL b[maxn], c[maxn], p[maxn*4], lz[maxn*4];
int lisan(int n, LL a[]);
void creat(int l, int r, int k);
void pushdown(int k);
bool cmp1(node a, node b);
bool cmp2(node a, node b);
void Update(int l, int r, int al, int ar, int x, int k);

int main()
{
    int n, m, q, i, j, k, len;
    LL ans = -1e16;
    scanf("%d %d %d", &n, &m, &q);
    for(i=1;i<=n;i++)
        scanf("%d %d", &atk[i].a, &atk[i].p);
    for(i=1;i<=m;i++){
        scanf("%d %d", &def[i].b, &def[i].p);
        b[i] = def[i].b;
    }
    for(i=1;i<=q;i++)
        scanf("%d %d %d", &mon[i].b, &mon[i].a, &mon[i].p);
    sort(atk+1, atk+1+n, cmp1);
    sort(mon+1, mon+1+q, cmp2);
    //离散化,初始化收益
    len = lisan(m, b);
    for(i=1;i<=len;i++)
        c[i] = -INF;
    for(i=1;i<=m;i++){
        int pos = lower_bound(b+1, b+1+len, def[i].b)-b;
        c[pos] = max(c[pos], -1LL*def[i].p);
    }
    for(i=len-1;i>=1;i--)
        c[i] = max(c[i], c[i+1]);
    creat(1, len, 1);
    //暴力考虑购买的武器
    j = 1;
    for(i=1;i<=n;i++)
    {
        //将攻击值变大所能击杀的怪物信息加入线段树中
        while(j<=q && mon[j].b < atk[i].a)
        {
            int pos = upper_bound(b+1, b+1+len, mon[j].a)-b;
            if(pos<=len)Update(1, len, pos, len, mon[j].p, 1);
            j++;
        }
        ans = max(ans, -atk[i].p+p[1]);
    }
    printf("%I64d\n", ans);
    return 0;
}

int lisan(int n, LL a[])
{
    sort(a+1, a+1+n);
    int top = 0, i;
    a[0] = a[1]-1;
    for(i=1;i<=n;i++)
        if(a[i] != a[top])a[++top] = a[i];
    return top;
}

void creat(int l, int r, int k)
{
    lz[k] = 0;
    if(l == r){
        p[k] = c[l];
        return;
    }
    int mid = (l+r)/2;
    creat(l, mid, 2*k);
    creat(mid+1, r, 2*k+1);
    p[k] = max(p[2*k], p[2*k+1]);
}

void Update(int l, int r, int al, int ar, int x, int k)
{
    if(l == al && r == ar){
        p[k] += x;
        lz[k] += x;
        return ;
    }
    pushdown(k);
    int mid = (l+r)/2;
    if(ar <= mid)Update(l, mid, al, ar, x, 2*k);
    else if(al>mid) Update(mid+1, r, al, ar, x, 2*k+1);
    else Update(l, mid, al, mid, x, 2*k), Update(mid+1, r, mid+1, ar, x, 2*k+1);
    p[k] = max(p[2*k], p[2*k+1]);
}

void pushdown(int k)
{
    if(lz[k])
    {
        p[2*k] += lz[k];
        p[2*k+1] += lz[k];
        lz[2*k] += lz[k];
        lz[2*k+1] += lz[k];
        lz[k] = 0;
    }
}

bool cmp1(node a, node b)
{
    return a.a < b.a;
}

bool cmp2(node a, node b)
{
    return a.b < b.b;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值