偏序+线段树——cf1320C

挺好的题

/*
每个武器攻击力ai,价格cai
每个装备防御力bi,价格cbi
每只怪兽攻击力xi,防御力yi,收益zi
    ai>yi && bi>xi 那么可以获得收益zi 
选择一件武器,一件装备,求最大收益 

武器装备按ai,bi升序排序
怪兽按yi升序排序,那么当遍历到第i、只怪兽时,只有aj>yi+1的武器才有用,贪心从[j,n]里找最便宜的武器
对于防具,只有bk>xi+1的防具才有用,但是不能保证bk>xi-1(因为是按yi升序排序的),所以转换成这只怪兽可以被多少防具防御
    开线段树维护一下贡献,每次查询后更新一次ans 
*/
#include<bits/stdc++.h>
using namespace std;
#define N 200005
#define ll long long 

struct A{ll a,c;}a[N];
struct B{ll b,c;}b[N];
struct D{ll x,y,z;}d[N];
int cmp1(A a,A b){return a.a<b.a;}
int cmp2(B a,B b){return a.b<b.b;}
int cmp3(D a,D b){return a.x<b.x;}
ll n,m,p,suf[N];//suf[i]表示[i+1,m]里装备最便宜的 

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
ll Max[N<<2],lazy[N<<2];
void build(int l,int r,int rt){
    if(l==r){Max[rt]=-b[l].c;return;}
    int m=l+r>>1;
    build(lson);
    build(rson);
    Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}
void pushdown(int rt){
    if(lazy[rt]){
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        Max[rt<<1]+=lazy[rt];
        Max[rt<<1|1]+=lazy[rt];
        lazy[rt]=0;
    }
}
void update(int L,int R,ll v,int l,int r,int rt){
    if(L<=l && R>=r){lazy[rt]+=v;Max[rt]+=v;return;}
    pushdown(rt);
    int m=l+r>>1;
    if(L<=m)update(L,R,v,lson);
    if(R>m)update(L,R,v,rson);
    Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); 
}

int main(){
    cin>>n>>m>>p;
    for(int i=1;i<=n;i++)scanf("%lld%lld",&a[i].a,&a[i].c);
    for(int i=1;i<=m;i++)scanf("%lld%lld",&b[i].b,&b[i].c);
    for(int i=1;i<=p;i++)scanf("%lld%lld%lld",&d[i].x,&d[i].y,&d[i].z);
    sort(a+1,a+1+n,cmp1);
    sort(b+1,b+1+m,cmp2);
    sort(d+1,d+1+p,cmp3);
    suf[n]=a[n].c;
    for(int i=n-1;i>=1;i--)
        suf[i]=min(suf[i+1],a[i].c);
    
    build(1,m,1);
    ll ans=-a[1].c-b[1].c;
    int pos1=1,pos2=1;
    for(int i=1;i<=p;i++){//按x从小到大枚举d[i] 
        ll X=d[i].x+1,Y=d[i].y+1;
        while(pos1<=n && a[pos1].a<X)pos1++;
        if(pos1==n+1)break;
        
        pos2=-1;
        int L=1,R=m,mid;
        while(L<=R){
            mid=L+R>>1;
            if(b[mid].b>=Y)
                R=mid-1,pos2=mid;
            else L=mid+1;
        }
        if(pos2>0 && pos2<=m)
            update(pos2,m,d[i].z,1,m,1);
        ans=max(ans,Max[1]-suf[pos1]);
    }
    
    cout<<ans<<'
';
} 
原文地址:https://www.cnblogs.com/zsben991126/p/12470456.html