zoukankan      html  css  js  c++  java
  • Codeforces Round #625 (Div. 1, based on Technocup 2020 Final Round)

    好久没写博客了、、、水一篇

    World of Darkraft: Battle for Azathoth

    题目链接:https://codeforces.com/contest/1320/problem/C

    题意:
             有N个武器,每个武器有它的价格;有M个盾牌,每个盾牌有它的价格
            有K个怪物,每个怪物的攻击力为 X , 防御力为 Y , 杀死怪后掉落的金币为 Z
            如果我们挑选的武器攻击力大于Xi,并且我们挑选的盾牌防御力大于Yi,则我们可以获得Zi个金币
            要求我们必从中挑选一个武器和一个盾牌,使我们可获得的总收益最大
    分析:
           假设我们选择的武器为 A(价格为CA), 盾牌为 B(价格为CB)
           而我们可以获得的利润为我们可以杀死的怪物们掉落的金币总和 - 武器价格 - 盾牌价格
           即 ans = 可获得金币和 - CA - CB
           一、预处理过程:
           ①、对武器排序,然后再枚举武器
           ②、让怪物按照X排序
           ③、权值线段树:
           下标为防御值,即[L , R]表示[防御值为L,防御值R]
           下标对应的值为金币,即tree[L] = 10 表示当盾牌防御力为L时可以获得的金币和为10
           同样我们开个a数组,其中a[i]表示攻击力为i的武器的价格

           过程开始之前,我们的武器已排序,怪物也已按 X 排序,我们用C数组表示怪物的属性值
           我们用双指针< i , j >来进行过程 —— i 表示武器 , j 表示怪物

           二、算答案过程:
           ①、我们枚举到i了,我们判断j这个怪物的攻击力是否小于i
           ②、如果小于i(c[j].x < i),那么如果我们选的盾牌防御力大于c[j].y,我们获得的金币是不是就可以加上c[j].z?
           也就是说,我们当前的武器是 i ,而某一盾牌防御力只要大于c[j].y,该盾牌可获得的金币和就可以算上c[j].z
           ③、当然因为购买盾牌也是要money的,所以我们购买的盾牌应该为max(该盾牌可获得的金币和 - 该盾牌的价格),即最大收益

           ①②③对应的代码为

    for(int i = 1 ;  i <= n ; i ++)
    {
        while(j <= k && c[j].x < i) 
        {
    //表示防御力大于c[j].y的盾牌   可获得的总收益都可以算上c[j].z
             update_range(c[j].y + 1 , n , c[pos].z) 
              j ++;
        }
        ans = max(ans, tree[1].maxn - a[i]);
    }

           有些细节就不多说了(实在太懒 -。-

    #include <bits/stdc++.h>
    #define rep(i, a, n) for (int i = a; i <= n; i++)
    #define per(i, n, a) for (int i = n; i >= a; i--)
    #define ll long long
    #define int long long
    using namespace std;
    const ll INF(0x3f3f3f3f3f3f3f3fll);
    const int inf(0x3f3f3f3f);
    const int N = 1e6 + 150;
    int a[N], b[N], n, m, k, tot, mi1 = INF, mi2 = INF;
    struct Tree
    {
        ll l, r, lazy, maxn;
    } tree[N << 2];
    void push_up(ll rt)
    {
        tree[rt].maxn = max(tree[rt << 1].maxn, tree[rt << 1 | 1].maxn);
    }
    void push_down(ll rt, ll length)
    {
        if (tree[rt].lazy)
        {
            tree[rt << 1].lazy += tree[rt].lazy;
            tree[rt << 1 | 1].lazy += tree[rt].lazy;
            tree[rt << 1].maxn += tree[rt].lazy;
            tree[rt << 1 | 1].maxn += tree[rt].lazy;
            tree[rt].lazy = 0;
        }
    }
    void build(ll l, ll r, ll rt)
    {
        tree[rt].lazy = 0, tree[rt].l = l, tree[rt].r = r;
        if (l == r)
        {
            tree[rt].maxn = -b[l];
            return;
        }
        ll mid = (l + r) >> 1;
        build(l, mid, rt << 1);
        build(mid + 1, r, rt << 1 | 1);
        push_up(rt);
    }
    void update_range(ll L, ll R, ll key, ll rt)
    {
        if (tree[rt].r < L || tree[rt].l > R)
            return;
        if (L <= tree[rt].l && R >= tree[rt].r)
        {
            tree[rt].maxn += key;
            tree[rt].lazy += key;
            return;
        }
        push_down(rt, tree[rt].r - tree[rt].l + 1);
        ll mid = (tree[rt].r + tree[rt].l) >> 1;
        if (L <= mid)
            update_range(L, R, key, rt << 1);
        if (R > mid)
            update_range(L, R, key, rt << 1 | 1);
        push_up(rt);
    }
    struct node{
        int x, y, z;
        bool operator<(const node &a) const{
            return x < a.x;
        }
    } c[N];
    signed main()
    {
        scanf("%lld %lld %lld", &n, &m, &k);
        rep(i, 1, n)
        {
            int pos, val;
            scanf("%lld %lld", &pos, &val);
            if (!a[pos])    a[pos] = val;
            else    a[pos] = min(a[pos], val);
            mi1 = min(mi1, val), tot = max(tot, pos);
        }
        rep(i, 1, m)
        {
            int pos, val;
            scanf("%lld %lld", &pos, &val);
            if (!b[pos])    b[pos] = val;
            else    b[pos] = min(b[pos], val);
            mi2 = min(mi2, val);
        }
        n = 0;
        per(i, N - 10, 1)
        {
            if (!b[i])    b[i] = b[i + 1];
            else if (b[i + 1])    b[i] = min(b[i], b[i + 1]);
            if (b[i] && !n)    n = i;
        }
        rep(i, 1, k) scanf("%lld %lld %lld", &c[i].x, &c[i].y, &c[i].z);
        sort(c + 1, c + 1 + k);
        int ans = -mi1 - mi2, j = 1;
        build(1, n, 1);
        rep(i, 1, tot)
        {
            if (a[i])
            {
                while (j <= k && c[j].x < i)
                {
                    update_range(c[j].y + 1, n, c[j].z, 1);
                    j++;
                }
                ans = max(ans, tree[1].maxn - a[i]);
            }
        }
        printf("%lld
    ", ans);
        return 0;
    }

     

     

     

    凡所不能将我击倒的,都将使我更加强大
  • 相关阅读:
    批量SSH操作工具---OmniTTY安装
    CentOS6.6修改主机名和网络信息
    浪潮服务器通过ipmitool获取mac地址
    linux批量执行工具omnitty使用方法
    操作系统下查看HBA卡信息wwn的方法
    Linux下multipath多路径配置
    IPMITOOL 配置BMC用户设置
    第五讲 对于耦合的认识 target/action设计模式 delegate设计模式 手势识别器
    UI第四讲.事件处理(按钮点击切换视图,触摸事件)
    UI第三讲.自定义视图 视图控制器 检测屏幕旋转
  • 原文地址:https://www.cnblogs.com/StarRoadTang/p/12400291.html
Copyright © 2011-2022 走看看