标签:== 区间 题目 problem 攻击 c++ 更新 turn inf
E. World of Darkraft: Battle for Azathoth
题目大意:
给你n个武器和m个防御,每一个武器有一个攻击值 a 和这个武器的价格,每一个防御有一个防御值b和这个防御的价格,有p个怪物,每一个怪物有一个防御值x攻击值y,和打赢这个怪物收获的价值z。
你买一个武器和一个防御,问最大的利润是多少(收获的价值减去花费),必须选一个武器和一个防御。
题解:
开始我以为这个题目是一个优先队列,然后发现不对。
其实cf上一般有 \(data \,srtuctures\) 这个标签的都是线段树。
而且一般cf上2000左右的线段树都比较简单,也不是说特别简单,就是可以自己想到的,而且套路就那么几种,基本上都是离线+排序,通过求差值放到线段树里面来维护,通过更新区间来更新点。。。
其实也不太记得了,以后有时间可以整理一下。
接下来正式说说这个题目的解析:
首先这个有三个值,一个是武器,一个是防御,一个是怪物。
首先对武器和防御进行排序,然后对怪物按照防御值进行排序,之后遍历武器,对于每一个攻击值a,找到武力值小于a的所有怪物,这个时候我怎么判断要哪个防御呢?也许你说可以二分,那么是不是每一个怪物都要二分一次?以后每次放入一个满足条件的怪物,是不是都需要对每一个怪物二分一次?那么这个复杂度很明显是过不了的,所以这个是需要我遍历到武器 $i $ 的时候就马上判断出这个武器最好和哪一个防御进行匹配,或者说和和一个防御进行匹配之后的最大利润。
这个地方就要用到线段树了,首先把所有的防御的位置的赋值成这个花费的负数,其他位置赋值为-inf,然后每次放入一个怪物,这个怪物的攻击值是y,就直接更新区间 \([y+1,end]\) 这个区间加上这个怪物的价值,表示对于所有防御值是 \([y+1,end]\) 的这个区间都可以收获这个怪物的价值(因为之前排过序,所以x可以保证一定满足)。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn= 1e6+10;
const int M = 1e6+2;
struct node{
int x,y,w;
node(int x=0,int y=0,int w=0):x(x),y(y),w(w){}
}a[maxn],b[maxn];
ll maxs[maxn<<2],lazy[maxn<<2];
bool cmp(node a,node b){
return a.x<b.x;
}
void push_up(int id){
maxs[id]=max(maxs[id<<1],maxs[id<<1|1]);
}
void modify(int id,int l,int r,int pos,ll w){
if(l==r){
maxs[id]=max(maxs[id],w);
return ;
}
int mid=(l+r)>>1;
if(pos<=mid) modify(id<<1,l,mid,pos,w);
else modify(id<<1|1,mid+1,r,pos,w);
push_up(id);
}
void push_down(int id) {
if (!lazy[id]) return;
lazy[id << 1] += lazy[id];
lazy[id << 1 | 1] += lazy[id];
maxs[id << 1] += lazy[id];
maxs[id << 1 | 1] += lazy[id];
lazy[id] = 0;
}
void update(int id,int l,int r,int x,int y,int val) {
if (x <= l && y >= r) {
lazy[id] += val;
maxs[id] += val;
return;
}
int mid = (l + r) >> 1;
push_down(id);
if (x <= mid) update(id << 1, l, mid, x, y, val);
if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, val);
push_up(id);
}
int main(){
int n,m,p;
scanf("%d%d%d",&n,&m,&p);
memset(maxs,0xef,sizeof(maxs));
for(int i=1;i<=n;i++){
int x,w;
scanf("%d%d",&x,&w);
a[i]=node(x,0,w);
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=m;i++){
int x,w;
scanf("%d%d",&x,&w);
modify(1,1,M,x,-w);
}
for(int i=1;i<=p;i++){
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
b[i]=node(x,y,w);
}
sort(b+1,b+1+p,cmp);
int now = 1;
ll ans = -inf64;
for(int i=1;i<=n;i++){
while(now<=p&&b[now].x<a[i].x){
update(1,1,M,b[now].y+1,M,b[now].w);
now++;
}
ans = max(ans,maxs[1]-a[i].w);
// printf("i=%d now=%d x=%d w=%d maxs=%d\n",i,now,a[i].x,a[i].w,maxs[1]);
}
printf("%lld\n",ans);
return 0;
}
E. World of Darkraft: Battle for Azathoth
标签:== 区间 题目 problem 攻击 c++ 更新 turn inf
原文地址:https://www.cnblogs.com/EchoZQN/p/13371177.html