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;
}
posted @ 2020-03-04 18:39  zhangxianlong  阅读(164)  评论(0编辑  收藏  举报