zoukankan      html  css  js  c++  java
  • CF1321-World of Darkraft: Battle for Azathoth (线段树+二维偏序)

    题意:

    题目大致意思是给你n把武器,m件防具,p个怪兽,接下来n行每行告诉你该武器的攻击力和花费,

    接下来m行告诉你该防具的防御力和花费,然后p行每行告诉你这个怪兽的攻击力,防御力以及打败这个

    怪兽可以获得的金钱数,当你的攻击力大于怪兽的防御力,并且你的防御力大于怪兽的攻击力时,你可

    以打败这个怪兽。你必须至少购买1件武器和1件防具,问你最多可以获得多少钱。

    链接:https://codeforces.com/contest/1321/problem/E

    思路:

    看了大神的题解,第一次知道二维偏序这种东西,然后可以用线段树解决这类问题。

    我们先将武器按照攻击力从小到大排序,再将防具按照防御力从小到大排序,然后将

    怪兽按照防御力从小到大排序,对防具建立线段树,每个叶子节点的初始值是使用该

    防具的花费,线段树的每个节点存该区间内能获得的最大收益,至于区间的更新,

    在当前武器的攻击力大于该怪物的防御力的情况下,要想打败这个怪物,那么防具的

    防御力必须大于怪物的攻击力,也就是说,我们要在防具中找到第一个防御力比怪物的

    攻击力大的位置 index ,然后更新[index,m]这段区间,区间内的每个点加上击败怪物

    的收益,代表在使用i这件武器的情况下,用这段区间内的任何一件防具均可击败该怪物

    。最后,我们只需要用tree[1](利润-防具的花费的最大值)-当前的武器的花费,就能得出在这种情况下的收益。

    代码如下

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 2e5 + 5;
    const int INF = 0x7fffffff;
    typedef long long ll;
    int tree[MAXN<<2],lazy[MAXN<<2],n,m,p;
    struct node
    {
        int ability,cost;
        node() {}
        node(int a,int b) : ability(a),cost(b) {}
        bool operator <(node temp)const
        {
            return ability<temp.ability;
        }
    } a[MAXN],b[MAXN];
    struct monster
    {
        int defend,attack,gain;
        monster() {}
        monster(int a,int b,int c) : attack(b),defend(a),gain(c) {}
        bool operator < (monster temp)const
        {
            return defend<temp.defend;
        }
    } c[MAXN];
    // 线段树查询区间最大值  
    void push_up(int node) { tree[node]=max(tree[node<<1],tree[node<<1|1]); } void build(int node,int l,int r) { //lazy[node]=0; if(l==r) { tree[node]=-b[l].cost; return; } int mid=(l+r)>>1; build(node<<1,l,mid); build(node<<1|1,mid+1,r); push_up(node); } void push_down(int node) { if(lazy[node]) { tree[node<<1]+=lazy[node]; tree[node<<1|1]+=lazy[node]; lazy[node<<1]+=lazy[node]; lazy[node<<1|1]+=lazy[node]; lazy[node]=0; } } void update(int node,int l,int r,int x,int y,int k) { if(x<=l&&y>=r) { tree[node]+=k; lazy[node]+=k; return; } push_down(node); int mid=(l+r)>>1; if(x<=mid) update(node<<1,l,mid,x,y,k); if(y>mid) update(node<<1|1,mid+1,r,x,y,k); push_up(node); } int main() { scanf("%d%d%d",&n,&m,&p); for(int i=1; i<=n; i++) scanf("%d%d",&a[i].ability,&a[i].cost); for(int i=1; i<=m; i++) scanf("%d%d",&b[i].ability,&b[i].cost); for(int i=1; i<=p; i++) scanf("%d%d%d",&c[i].defend,&c[i].attack,&c[i].gain); sort(a+1,a+1+n); sort(b+1,b+1+m); sort(c+1,c+1+p); build(1,1,m); int now=1; int ans=-INF; for(int i=1; i<=n; i++) { while(now<=p&&c[now].defend<a[i].ability) { //printf("%d ",c[now].attack); int index=upper_bound(b+1,b+1+m,node(c[now].attack,0))-b;//找出第一个大于这个怪兽攻击力的位置 if(index<=m) { update(1,1,m,index,m,c[now].gain);//区间更新; } now++; } ans=max(ans,tree[1]-a[i].cost); } printf("%d ",ans); }
  • 相关阅读:
    angularJS CDN
    Python matplotlib 交互模式
    Selenium
    流程图
    Linux Shell脚本教程
    FTP没权限直接删除目录,写的一个小工具循环删除
    正则星号隐藏手机号码的后4位
    日志函数
    夺命雷公狗C/C++-----3---helloworld的诞生
    夺命雷公狗C/C++-----2---开发工具篇
  • 原文地址:https://www.cnblogs.com/ljxdtc666/p/12430136.html
Copyright © 2011-2022 走看看