Codeforces Round #625 E - World of Darkraft: Battle for Azathoth - 線段樹

題目鏈接:https://codeforces.com/contest/1321/problem/E
題目大意:
有n個武器。每個有屬性攻擊力:a[i],價格:ca[i]。
有m個盾牌。每個有屬性防禦力:b[i],價格:bc[i]。
有k個怪物。每個有防禦力xk, 攻擊力yk,價值zk。
現在你必須並且只能買一個武器和一個盾牌。如果你的攻擊力>怪物的防禦力並且你的防禦力>怪物的攻擊力。那麼你就可以打敗這隻怪物並且得到這隻怪物價值的錢。所以你的收益爲所有擊敗怪物的價值和-購買武器和盾牌的錢。現在讓你最大化收益。
在這裏插入圖片描述
思路:我們枚舉武器攻擊力a[i]。那麼我們可以打敗的怪物只可能是x[i]<a[i]。我們我們把以盾牌的防禦力y[i]爲軸建立線段樹。我們先把所有盾牌加入線段樹。值爲(-價格)。

那麼我們在枚舉a[i]時把所有x[i]<a[i]的怪物加入線段樹。(b[i], k)。那麼線段樹就可以logn查詢到現在的買當前武器,買任意盾牌可以收益的最大值。

線段樹維護:sum爲怪物得到價格前綴和,mx爲買當前區間盾牌可能收益的最大值。分別維護就可以了

#include<bits/stdc++.h>
#define LL long long
#define mid (l+r)/2
using namespace std;

struct ode{
    int x, y;
}a[200005];

struct gw{
    int x, y, z;
}c[200005];

struct Node{
    LL l, r;
    LL sum, mx, pos;
}node[5000000];

void BT(LL i, LL l, LL r){
    node[i].l=l;
    node[i].r=r;
    if(l==r){
        node[i].mx=node[i].sum=node[i].pos=0;
        return ;
    }
    BT(i<<1, l, mid);
    BT((i<<1)+1, mid+1, r);
}

void GX(LL i, LL x, LL y, LL z){

    if(node[i].l==node[i].r){
        if(z==0){
            node[i].sum+=y;
        }
        else{
            if(node[i].pos==0){
                node[i].mx=y;
                node[i].pos=1;
            }
            else{
                node[i].mx=max(node[i].mx, y);
                node[i].pos=1;
            }
        }
        return ;
    }
    if(x<=(node[i].l+node[i].r)/2){
        GX(i<<1, x, y, z);
    }
    else{
        GX((i<<1)+1, x, y, z);
    }
    if(node[i<<1].pos&&node[(i<<1)+1].pos){
        node[i].mx=max(node[i<<1].mx, node[(i<<1)+1].mx+node[i<<1].sum);
        node[i].pos=1;
    }
    else if(node[i<<1].pos){
        node[i].mx=node[i<<1].mx;
        node[i].pos=1;
    }
    else if(node[(i<<1)+1].pos){
        node[i].mx=node[(i<<1)+1].mx+node[i<<1].sum;
        node[i].pos=1;
    }
    node[i].sum=node[i<<1].sum+node[(i<<1)+1].sum;
}

LL CX(){
    return node[1].mx;
}

int cmp(ode a, ode b){

    return a.x<b.x;
}


int main(){

    int n, m, k, x, y, z, tot=1;
    scanf("%d%d%d",&n, &m, &k);
    for(int i=1; i<=n; i++){
        scanf("%d%d", &a[i].x, &a[i].y);
    }
    sort(a+1, a+1+n, cmp);
    BT(1, 1, 1e6);
    for(int i=1; i<=m; i++){
        scanf("%d%d", &x, &y);
        GX(1, x, -y, 1);
    }
    for(int i=1; i<=k; i++){
        scanf("%d%d%d", &c[i].x, &c[i].y, &c[i].z);
    }
    LL mx=-(1ll<<60);
    sort(c+1, c+k+1, [](gw &a, gw &b){return a.x<b.x;});
    for(int i=1; i<=n; i++){
        while(tot<=k&&c[tot].x<a[i].x){
            GX(1, c[tot].y, c[tot].z, 0);
            tot++;
        }
        LL ans=CX();
        mx=max(mx, ans-a[i].y);
    }
    printf("%lld\n", mx);

    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章