攻击防御2维影响因素,通常这类题我们枚举一维,另一维用线段树快速维护。
枚举武器,按武器攻击从小到大枚举。
然后把当前武器能消灭的怪物的钱,放到对应的攻击上去(在线段树里维护)这样保证线段树里的怪物的防御力始终低于当前武器的攻击力。然后就是快速找到线段树里怪物攻击力小于某个防御力 所获得的最大金币
那么我们线段树节点i的初值是:购买防具,达到防御i,所需的最少金币。
那么线段树的更新:每次加入一个怪物,改怪物防御力x,我们让x+1,sz区间都加上怪物的赏金,表示只要防御大于x+1,就可以拿到这个怪物的赏金。
最终线段树区间最大值,就是我们需要的结果,即购买防具获得的最大赏金。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
//#define a(i,j) a[(i)*(m+2)+(j)] //m是矩阵的列数
const double PI= acos(-1.0);
const int M = 2e6+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y,int z){ee[++cnt].nxt=head[x],ee[cnt].to=y,ee[cnt].val=z,head[x]=cnt;}
*/
int sz;
struct node{
ll x,m;
}a[M],b[M];
struct mon{
ll a,b,m;
}c[M];
bool cmp(node a,node b)
{
if(a.x==b.x)return a.m<b.m;
return a.x<b.x;
}
bool cmp1(mon a,mon b)
{
return a.a<b.a;
}
ll na[M];
ll mx[M<<2];
ll tg[M<<2];
void bd(int o,int l,int r)
{
if(l==r)
{
mx[o]=-na[l];
return ;
}
int m=(l+r)/2;
bd(ls,l,m);
bd(rs,m+1,r);
mx[o]=max(mx[ls],mx[rs]);
}
void pd(int o,int l,int r)
{
if(!tg[o])return ;
int m=(l+r)/2;
mx[ls]+=tg[o];tg[ls]+=tg[o];
mx[rs]+=tg[o];tg[rs]+=tg[o];
tg[o]=0;
}
void up(int o,int l,int r,int x,int y,int d)
{
// cout<<l<<" "<<r<<" "<<x<<" "<<y<<endl;
if(x<=l&&r<=y)
{
mx[o]+=d;
tg[o]+=d;
return ;
}
pd(o,l,r);
int m=(l+r)/2;
if(x<=m)up(ls,l,m,x,y,d);
if(y>m)up(rs,m+1,r,x,y,d);
mx[o]=max(mx[ls],mx[rs]);
}
ll qu(int o,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
return mx[o];
int m=(l+r)/2;
pd(o,l,r);
ll ma=-1e18;
if(x<=m)ma=max(ma,qu(ls,l,m,x,y));
if(y>m)ma=max(ma,qu(rs,m+1,r,x,y));
return ma;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n,m,p;
sz=1e6+100;
cin>>n>>m>>p;
for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].m;
for(int i=1;i<=m;i++)cin>>b[i].x>>b[i].m;
for(int i=1;i<=p;i++)
cin>>c[i].b>>c[i].a>>c[i].m;
sort(b+1,b+1+m,cmp);
sort(a+1,a+1+n,cmp);
sort(c+1,c+1+p,cmp1);
na[0]=-1;
ll id=n,mi=1e16;
for(int i=sz;i>=1;i--)
{
while(a[id].x>=i&&id)mi=min(a[id].m,mi),id--;
na[i]=mi;//购买防具获得防御力i,所需的最少钱数
// if(i<100)cout<<i<<" "<<na[i]<<endl;
}
bd(1,1,sz);
ll ma=-1e18;
id=1;
for(int i=1;i<=m;i++)
{
ll tp=b[i].x,tm=b[i].m;
while(c[id].a<tp&&id<=p)up(1,1,sz,c[id].b+1,sz,c[id].m),id++;
ll z=mx[1];
ma=max(z-tm,ma);
}
cout<<ma<<endl;
return 0;
}
/*
10 10 10
51 87
68 743
82 1284
73 936
55 242
89 1554
58 357
66 666
62 512
51 87
92 1670
56 280
56 280
91 1631
77 1091
89 1554
61 473
98 1901+1544
77 1091
77 1091
86 15 386
43 58 386
68 33 386
39 62 386
95 6 386
74 27 386
94 7 386
17 84 386
97 4 386
45 56 386
*/