zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 114 (Rated for Div. 2) C. Slay the Dragon


    题目链接

    题目大意

    给你(n)个人,每个人有(a_i)点攻击力,你需要选(1)个人去击杀敌人,剩下的人守卫。当选中的人的攻击力大于等于敌人的防御力(x)且剩下的人攻击力之和大于等于敌人的攻击力(y),则算成功。你可以(1)枚金币提高任何一个人的攻击力,问你最小的花费是多少。

    题目分析

    给定一个敌人((防御力,攻击力)=(x,y)),令派出的人的攻击力是(k),所有人的攻击力之和为(sum),那么花费的金币数为: (max(0, x - k) + max(0, y - (sum - k)))。之后对每个人的能力进行枚举,显然这么做会超时。

    先对(n)个人的攻击力进行排序,进行去重操作,因为存在攻击力相同的情况,没有必要重复判断。

    之后,二分找到第一个大于等于(x)的元素,那么之后的元素就没有必要枚举,因为金币的花费会越来越多。之后我们从找到的元素再往前枚举,此时(max(0, x - k))会逐渐增大,(会逐渐max(0, y - (sum - k)))减小,总的趋势是金币数先小后大,所以我们只需要向前枚举,找到金币的极小点即可。

    AC代码

    #include <bits/stdc++.h>
    #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
    using namespace std;
    
    constexpr int N = 2e5 + 100;
    typedef long long LL;
    int n, m;
    LL a[N], sum;
    
    inline LL cost(LL x, LL y)
    {
        LL res = LONG_LONG_MAX;
        int k = lower_bound(a, a + n, x) - a;
        if (k == n) k --;
        for (int i = k; i; i--)
        {
            LL t = max(0LL, x - a[i]) + max(0LL, y - sum + a[i]);
            if (res > t) res = t;
            else break;
        }
        return res;
    }
    
    
    int main()
    {
        // 神奇,本题比用scanf快好几倍
        io;
        cin >> n;
        for (int i = 1; i <= n; i++) cin >> a[i], sum += a[i];
        sort(a + 1, a + n + 1);
        n = unique(a + 1, a + n + 1) - a;
    
        cin >> m;
        while (m --)
        {
            LL x, y; cin >> x >> y;
            cout << cost(x, y) << '
    ';
        }
    
        return 0;
    }
    
    
  • 相关阅读:
    Matlab 将RGB 图像转换成YCrCb图像
    dotnet中文字符工具类
    dotnet验证参数
    dotnet + LinQ 按照指定的字段 和 排序方式排序
    Angulaur导入其他位置的样式
    Angular4.x跨域请求
    Spring Cloud微服务实战:手把手带你整合eureka&zuul&feign&hystrix
    关于JVM加载class文件和类的初始化
    JVM垃圾回收机制概述
    深入理解JVM
  • 原文地址:https://www.cnblogs.com/FrankOu/p/15316020.html
Copyright © 2011-2022 走看看