题意
购买武器和装备,攻击力和防御力都大于某个怪物的时候,就可以获取他的收益。
求总收益(去掉购买的武器和装备的钱)最大
题解
首先武器和装备的最佳价格一定是随着属性的增加而增加的。
所以可以用后缀最小值来获得,当然我用的是单调队列。
得到价格后,我们考虑排序怪物的攻击力。
遍历,每次得到大于其攻击力的最小武器价格,然后需要找到所有遍历过的我能获得最大收益。
考虑线段树。
总共防御只有
,我们预先处理出每个点要购买达到大于该点值的防御装备的最小价格,在该点减去该价格,然后每次加入新怪物的时候,因为对后面的防御值都有贡献,所以实际更新区间为
。(不取
的原因是我们处理的时候都是大于该点。)
然后取全局最值即可。
注意只买装备的特判。
#include<bits/stdc++.h>
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e6+500000;
struct tree2{
tree2 *lson,*rson;
ll x,lazy;
}dizhi[maxn<<2],*root=&dizhi[0];
int n,m,p,t=1,len=1e6+500;
ll A[maxn];
void push_up(tree2 *tree,int l,int r){
tree->x=max(tree->lson->x,tree->rson->x);
}
void push_down(tree2 *tree,int l,int r){
if(!tree->lazy)return ;
tree->lson->x+=tree->lazy;
tree->rson->x+=tree->lazy;
tree->lson->lazy+=tree->lazy;
tree->rson->lazy+=tree->lazy;
tree->lazy=0;
}
void build(tree2 *tree,int l,int r){
if(l==r){
tree->x=A[l];
return ;
}
tree->lson=&dizhi[t++];
tree->rson=&dizhi[t++];
int mid=(l+r)>>1;
build(tree->lson,l,mid);
build(tree->rson,mid+1,r);
push_up(tree,l,r);
}
void update(tree2 *tree,int l,int r,int x,int y,ll d){
if(x<=l&&r<=y){
tree->x+=d;
tree->lazy+=d;
return ;
}
push_down(tree,l,r);
int mid=(l+r)>>1;
if(x<=mid)update(tree->lson,l,mid,x,y,d);
if(y>mid)update(tree->rson,mid+1,r,x,y,d);
push_up(tree,l,r);
}
ll query(tree2 *tree,int l,int r,int x,int y){
if(x<=l&&r<=y)return tree->x;
push_down(tree,l,r);
int mid=(l+r)>>1;
ll t1=-inf,t2=-inf;
if(x<=mid)t1=query(tree->lson,l,mid,x,y);
if(y>mid)t2=query(tree->rson,mid+1,r,x,y);
return max(t1,t2);
}
deque<pair<int,int> >dq;
vector<pair<int,int> >weapens;
vector<pair<int,int> >armor;
vector<pair<int,int> >G;
vector<pair<int,pair<int,int> > >monster;
int main(){
cin>>n>>m>>p;
G.clear();
ll L=inf,R=inf;
for(int i=1;i<=n;i++){
int l,r;scanf("%d%d",&l,&r);
G.push_back(make_pair(l,r));
L=min(L,1ll*r);
}
sort(G.begin(),G.end());
for(int i=0;i<G.size();i++){
while(!dq.empty()&&G[i].second<=dq.back().second)dq.pop_back();
dq.push_back(make_pair(G[i].first,G[i].second));
//cout<<G[i].first<<" "<<G[i].second<<endl;
}
while(!dq.empty()){
weapens.push_back(make_pair(dq.front().first,dq.front().second));
dq.pop_front();
}
G.clear();
for(int i=1;i<=m;i++){
int l,r;scanf("%d%d",&l,&r);
G.push_back(make_pair(l,r));
R=min(R,1ll*r);
}
sort(G.begin(),G.end());
for(int i=0;i<G.size();i++){
while(!dq.empty()&&G[i].second<=dq.back().second)dq.pop_back();
dq.push_back(make_pair(G[i].first,G[i].second));
}
while(!dq.empty()){
armor.push_back(make_pair(dq.front().first,dq.front().second));
dq.pop_front();
}
int pos,git;ll val;
pos=-1,git=-1,val=-inf;
for(int i=1;i<=len;i++){
while(git<=i&&pos+1<armor.size()){
pos++;
git=armor[pos].first;
val=armor[pos].second;
}
if(git>i)A[i]=-val;
else A[i]=-inf;
}
build(root,1,len);
for(int i=1;i<=p;i++){
int l,r,mid;scanf("%d%d%d",&l,&r,&mid);
monster.push_back(make_pair(l,make_pair(r,mid)));
}
sort(monster.begin(),monster.end());
ll ans=-L-R,now=0;
pos=-1,git=-1,val=-inf;
for(int i=0;i<monster.size();i++){
int attack=monster[i].first,defence=monster[i].second.first,profit=monster[i].second.second;
while(git<=attack&&pos+1<weapens.size()){
pos++;
git=weapens[pos].first;
val=weapens[pos].second;
}
update(root,1,len,defence,len,profit);
if(git>attack){
now=-val+root->x;
ans=max(ans,now);
}
}
cout<<ans<<endl;
}