1320C - World of Darkraft: Battle for Azathoth 枚举+逐步处理降维+线段树优化

攻击防御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
*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值