zoukankan      html  css  js  c++  java
  • E. World of Darkraft: Battle for Azathoth

    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
    ",i,now,a[i].x,a[i].w,maxs[1]);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    linux下将一个大的文件拆分成若干小文件
    linux远程下载文件 的两种方法之 ftp命令和scp命令
    Python正则表达式的七个使用范例
    isinstance()和type()
    “可变的”tuple
    Tomcat常用面试题
    Tomcat常用配置详解
    Java工程师该如何编写高效代码?
    收集100条实用的网络知识
    MySQL 19个规则数据库设计总结
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13371177.html
Copyright © 2011-2022 走看看