CodeForces-1320C World of Darkraft: Battle for Azathoth 【权值线段树+思维】

题意:

  有 \(n\) 件武器,每件武器的攻击力为:\(a_i\),花费为:\(ca_i\);有 \(m\) 件盾,每件盾的防御力为:\(b_i\),花费为:\(cb_i\)\(Roma\) 必须从中选出一件武器和一件盾牌,来攻击怪兽。每个怪兽有三个数值:攻击力 \(x_i\),防御力 \(y_i\),价值 \(z_i\)\(Roma\) 要想打败一个怪兽,其选择的武器和盾牌必须满足:\(a_i>y_i,b_i>x_i\),每打败一只怪兽就会获得其价值。最终的总获益为打败怪兽所获价值 \(-\) 买武器和盾牌的花费。求出 \(Roma\) 所能获得的最大利益。

分析:

  先把武器的攻击力从小到大排序,求选择第 \(i\) 件武器时找到适当的盾牌来使得利益最大。

代码:

(注意不同盾牌的防御可能重复,要选择花费最小的)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int N=2e5+5;
ll tree[N<<2],lazy[N<<2];
P wea[N],arm[N];
int b[N];
struct node
{
    int x,y,z;
    bool operator <(const node b)const
    {
        return x<b.x;
    }
}mon[N];
void build(int l,int r,int rt)
{
    lazy[rt]=0;
    if(l==r)
    {
        tree[rt]=0;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
}
void pushdown(int rt)
{
    if(lazy[rt])
    {
        tree[rt<<1]+=lazy[rt];
        tree[rt<<1|1]+=lazy[rt];
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        lazy[rt]=0;
    }
}
void update(int l,int r,int L,int R,int val,int rt)
{
    if(L<=l&&r<=R)
    {
        tree[rt]+=val;
        lazy[rt]+=val;
        return;
    }
    int mid=(l+r)>>1;
    pushdown(rt);
    if(L<=mid)
        update(l,mid,L,R,val,rt<<1);
    if(R>mid)
        update(mid+1,r,L,R,val,rt<<1|1);
    tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
}
int main()
{
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&wea[i].first,&wea[i].second);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&arm[i].first,&arm[i].second);
        b[i]=arm[i].first;
    }
    for(int i=1;i<=k;i++)
        scanf("%d%d%d",&mon[i].x,&mon[i].y,&mon[i].z);
    sort(wea+1,wea+1+n);
    sort(arm+1,arm+1+m);
    sort(b+1,b+1+m);
    sort(mon+1,mon+1+k);
    int len=unique(b+1,b+1+m)-b-1;//把盾的防御力排序
    for(int i=1;i<=m;i++)
    {
        while(i>1&&i<=m&&arm[i].first==arm[i-1].first)
            i++;
        int p=lower_bound(b+1,b+1+len,arm[i].first)-b;
        update(1,len,p,p,-arm[i].second,1);//购买该盾牌的花费
    }
    int j=1;
    ll ans=-1e16;
    for(int i=1;i<=n;i++)
    {
        while(j<=k&&mon[j].x<wea[i].first)//怪兽的防御力<武器攻击力
        {
            int p=upper_bound(b+1,b+1+len,mon[j].y)-b;
            if(p<=len)
                update(1,len,p,len,mon[j].z,1);
            j++;
        }
        ans=max(ans,tree[1]-wea[i].second);
    }
    printf("%lld\n",ans);
    return 0;
}

参考博客(分块做法)

猜你喜欢

转载自www.cnblogs.com/1024-xzx/p/12398787.html
今日推荐