Codeforces Round #625 Div1 C,二维偏序,排序+线段树

题目

题意:

有若干武器A,攻击力A1,费用A2,
有若干铠甲B,防御力B1,费用B2,
有若干怪兽M,攻击力M1,防御力M2,奖励M3
你可以选择一把武器,一个铠甲,打败所有攻击和防御都严格小的怪兽,问最大收益。

思路:

典型的二维偏序问题,把攻击和防御想象成二维的坐标轴,我们要找到的其实就是一个矩形里(0,0)~(x,y)里收益-这个矩形的花费的最大值。我们可以排序一维,另一维用线段树维护,枚举的时候往里面加怪兽就好。

代码:

#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define PB push_back
#define LL long long
#define pii pair<LL,LL>
#define MEM(x,y) memset(x,y,sizeof(x))
#define bug(x) cout<<"debug "#x" is "<<x<<endl;
#define FIO ios::sync_with_stdio(false);
#define ALL(x) x.begin(),x.end()
#define LOG 20
#define lson(x) ((x)<<1)
#define rson(x) ((x)<<1|1)
const int maxn=5e6;
const LL inf = 2e9;
int N = 1e6;
LL n,m,P,sum[maxn],lazy[maxn];
pii A[maxn],B[maxn];
pair<int,pii> MO[maxn];
void push_down(int p){
    lazy[lson(p)]+=lazy[p];
    lazy[rson(p)]+=lazy[p];
    lazy[p]=0;
}
void modify(int tr,int l,int r,int L,int R,int v){
    if(r<L||l>R)return;
    if(L<=l&&r<=R){
        lazy[tr]+=v;
        return;
    }
    push_down(tr);
    int mid=(l+r)/2;
    modify(rson(tr),mid+1,r,L,R,v);
    modify(lson(tr),l,mid,L,R,v);
    sum[tr]=max(sum[lson(tr)]+lazy[lson(tr)],sum[rson(tr)]+lazy[rson(tr)]);
    return ;
}
int main(){
    FIO;
    LL ans= -inf;
    cin>>n>>m>>P;
    for(int i=1;i<=n;i++) cin>>A[i].X>>A[i].Y;
    for(int i=1;i<=m;i++) cin>>B[i].X >>B[i].Y;
    for(int i=1;i<=P;i++) cin>>MO[i].X >>MO[i].Y.X >>MO[i].Y.Y;
    sort(MO+1,MO+P+1);
    sort(A+1,A+n+1);
    sort(B+1,B+m+1);
    MEM(lazy,0);MEM(sum,0);
    N = m;
    for(int i=1;i<=m;i++) modify(1,1,N,i,i,-B[i].Y);
    for(int idx=1,i=1;i<=n;i++){
        while(MO[idx].X<A[i].X&&idx<=P){
            int it = upper_bound(B+1,B+1+m,make_pair(MO[idx].Y.X,inf)) - B;
            if(it<=N)modify(1,1,N,it,N,MO[idx].Y.Y);
            idx++;
        }
        ans=max(ans,sum[1]+lazy[1]-A[i].Y);
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zhangxianlong/p/12411362.html