codeforces round #625 (div2) E World of Darkraft: Battle for Azathoth

题目链接:https://codeforces.com/contest/1321/problem/E

题意:给出n件武器(攻击力a[i]和价格ca[i]),m件盔甲(防御力b[i]和价格cb[i]),p个怪物(攻击力x[i],防御力y[i],价值z[i]),开始时必须购买一件武器和一件盔甲,假设武器的攻击力为a,盔甲的防御力为b,那么可以打败所有x[i]<b且y[i]<a的怪物,并获得这些怪物的价值,求利润最大是多少(利润=获得的价值-买武器和盔甲的成本)

思路参考博客:https://www.cnblogs.com/heyuhhh/p/12394164.html

思路:

  • 当不能打败一个怪物时,直接取最便宜的武器和最便宜的盔甲即可。
  • 当至少打败一个怪物时,我们枚举所打败的怪物中y[i]最大的,要使a>y[i],根据贪心可以选出a>y[i]的花费最少的武器,具体做法是根据武器的伤害值a[i]排序,二分查找>y[i]的第一个武器,下标记为l,用后缀记录下标大于l的最低花费。
  • 记N=1e6+4(b[i]的上限),现在就是对于要找[x[i]+1 , N]中的b使得利润最大。
  • 用线段树维护对于每个b,获得的利润的最大值,支持区间添加和区间查询。每次枚举将该怪物的价值(mst[i].z) update到b的区间[mst[i].y+1 , N]。
  • 要提醒的是这里的N不能等于1e6,要大于1e6。因为尽管b的上限是1e6,但是一旦数据中存在mst[i].y=1e6的情况,就会更新[mst[i].y+1 , N]这个区间,所以必须满足N >= 1e6+1.

AC code:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int maxn=1e6+5;
const int inf=0x3f3f3f3f;
typedef pair<int,int> PII;
typedef long long LL;
int n,m,p,N,mina[maxn],minb[maxn];
PII a[maxn],b[maxn];
LL tr[maxn<<2],lz[maxn<<2],Minc[maxn],ans;

struct node1{
    int x,y,z;
}mst[maxn];

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

bool cmp2(node1 a,node1 b){
    return a.x<b.x;
}

void pushup(int u){
    tr[u]=max(tr[u<<1],tr[u<<1|1]);
}

void build(int u,int l,int r){
    if(l==r){
        tr[u]=-Minc[l];
        return;
    }
    int mid=(l+r)>>1;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
    pushup(u);
}

void pushdown(int u){
    tr[u<<1]+=lz[u];
    lz[u<<1]+=lz[u];
    tr[u<<1|1]+=lz[u];
    lz[u<<1|1]+=lz[u];
    lz[u]=0;
}

void update(int u,int l,int r,int L,int R,LL v){
    if(l>=L&&r<=R){
        tr[u]+=v;
        lz[u]+=v;
        return;
    }
    if(lz[u]) pushdown(u);
    int mid=(l+r)>>1;
    if(L<=mid) update(u<<1,l,mid,L,R,v);
    if(R>mid) update(u<<1|1,mid+1,r,L,R,v);
    pushup(u);
}

LL query(int u,int l,int r,int L,int R){
    if(l>=L&&r<=R){
        return tr[u];
    }
    if(lz[u]) pushdown(u);
    int mid=(l+r)>>1;
    LL res=-1e18;
    if(L<=mid) res=query(u<<1,l,mid,L,R);
    if(R>mid) res=max(res,query(u<<1|1,mid+1,r,L,R));
    pushup(u);
    return res;
}

int main(){
    scanf("%d%d%d",&n,&m,&p);
    for(int i=1;i<=n;++i)
        scanf("%d%d",&a[i].first,&a[i].second);
    for(int i=1;i<=m;++i)
        scanf("%d%d",&b[i].first,&b[i].second);
    for(int i=1;i<=p;++i)
        scanf("%d%d%d",&mst[i].x,&mst[i].y,&mst[i].z);
    sort(a+1,a+n+1,cmp1);
    sort(b+1,b+m+1,cmp1);
    sort(mst+1,mst+p+1,cmp2);
    mina[n+1]=inf,minb[m+1]=inf;
    for(int i=n;i>=1;--i)
        mina[i]=min(mina[i+1],a[i].second);
    for(int i=m;i>=1;--i)
        minb[i]=min(minb[i+1],b[i].second);
    N=maxn-1;
    for(int i=1;i<=N;++i)
        Minc[i]=1e18;
    for(int i=1;i<=m;++i)
        Minc[b[i].first]=min(Minc[b[i].first],(LL)b[i].second);
    build(1,1,N);
    ans=-mina[1]-minb[1];
    for(int i=1;i<=p;++i){
        update(1,1,N,mst[i].y+1,N,(LL)mst[i].z);
        LL t=query(1,1,N,mst[i].y+1,N);
        int l=1,r=n,mid;
        while(l<=r){
            mid=(l+r)>>1;
            if(a[mid].first>mst[i].x) r=mid-1;
            else l=mid+1;
        }
        ans=max(ans,t-(LL)mina[l]);
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/FrankChen831X/p/12398755.html
今日推荐