码迷,mamicode.com
首页 > 其他好文 > 详细

E. World of Darkraft: Battle for Azathoth

时间:2020-07-24 15:46:28      阅读:96      评论:0      收藏:0      [点我收藏+]

标签:==   区间   题目   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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!