陕西计算机学会SYAP2025年1月月赛-新手组T4 小P采灵芝

题目描述

小P踩着厚厚的积雪,踏入了一片雪山的神秘领域。这里是高耸入云的雪山之巅,寒风凛冽,温度骤降。随着海拔的升高,环境变得更加恶劣,但也正是这样的环境,孕育出了许多珍贵的灵芝。这些灵芝顽强地生长在寒冷的环境中,环境越恶劣,它们的品质更加优良,疗效更加卓越。

共有 n n n 座雪山,第 i i i 座雪山的最高海拔为 h i h_i hi 米,山峰上海拔第 1 ∼ h i 1\sim h_i 1hi 米的位置都有一株灵芝,海拔越高疗效越好。

小P最多可以采摘 k k k 株灵芝,由于小P的包太小,每次只能装下一株灵芝。也就是说,小P每次上山只能够采摘一株灵芝,摘完之后就得下山。

请你帮小P计算,满足所有采摘的灵芝都尽可能优良的前提下,小P上山的总攀登里程为多少米?

注意:对于不同的雪山,海拔相同的灵芝品质也相同。


输入格式

第一行 2 2 2 个正整数 n , k n, k n,k ,表示雪山的数量与最多可以采摘的灵芝数量。

第二行是 n n n 个正整数,第 i i i 个数字表示第 i i i 座雪山的最高海拔 h i h_i hi

提示:输入量较大,建议使用更加快速的输入方式。

输出格式

一个整数,表示满足所有采摘的灵芝都尽可能优良的前提下,小P上山的总攀登里程为多少米。

样例输入 1

3 5
100 50 102

样例输出 1

502

样例输入 2

2 2023
2 3

样例输出 2

9

样例输入 3

5 114
514 528 526 517 522

样例输出 3

58266

数据范围

测试点 n n n k k k
1 ∼ 4 1\sim 4 14 1 ≤ n ≤ 100 1\leq n\leq 100 1n100 1 ≤ k ≤ 100 1\leq k\leq 100 1k100
5 ∼ 8 5\sim 8 58 1 ≤ n ≤ 2000 1\leq n\leq 2000 1n2000 1 ≤ k ≤ 2000 1\leq k\leq 2000 1k2000
9 ∼ 16 9\sim 16 916 1 ≤ n ≤ 1 0 6 1\leq n\leq 10^6 1n106 1 ≤ k ≤ 1.1 × 1 0 7 1\leq k\leq 1.1\times 10^7 1k1.1×107
17 ∼ 20 17\sim 20 1720 1 ≤ n ≤ 1 0 6 1\leq n\leq 10^6 1n106 1 ≤ k ≤ 2 × 1 0 9 1\leq k\leq 2\times 10^9 1k2×109

对于所有测试点,均满足 1 ≤ h i ≤ 2 × 1 0 9 1\leq h_i\leq 2\times 10^9 1hi2×109

样例解释

样例一中,第 1 1 1 座山选择了 2 2 2 株灵芝,分别在海拔第 100 100 100 米 与第 99 99 99 米。第 3 3 3 座山选择了 3 3 3 株灵芝,分别在海拔第 102 102 102 101 101 101 100 100 100 米,共 502 502 502 米。

解析

二分法,详见代码:

#include<bits/stdc++.h>
using namespace std;
int n, k;
int h[1000005];
long long ans = 0;
//取海拔x及以上的灵芝是否不超过要求,不超过返回true,超过返回fals
bool check(long long x) {
    long long sum = 0;
    for(int i = 1; i <= n; i++) {
        if (h[i] >= x) { //当前山峰大于等于x
            sum += h[i] - x + 1; //将x及以上的灵芝都采了
        }
        if (sum > k) return false; //若超过需求,返回false
    }
    return true;//否则返回true
}
int main() {
    cin >> n >> k;
    for(int i = 1; i <= n; i++) { //输入
        cin >> h[i];
    }
    long long left = 0;
    long long right = 2e9 + 1; //肯定不够
    while(left + 1 < right) { //二分求刚好不能满足需求的最低海拔(right)
        long long mid = (left + right) / 2;
        if (check(mid) == true) {
            right = mid;
        } else {
            left = mid;
        }
    }
    for(int i = 1; i <= n; i++) { //将right及以上的灵芝都采了,计算攀登里程
        if (h[i] >= right) {
            k -= h[i] - right + 1; //计算剩余灵芝数量
            ans += (right + h[i]) * (h[i] - right + 1) / 2;
        }
    }
    if (right > 1) { //补足剩余灵芝
        ans += (right - 1) * k;
    }
    cout << ans;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长春高老师信奥工作室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值