【HNU】数据结构-实验-算法-建造水族馆

这是HNU数据结构课程的实验八,来源于Codeforces 1873E。

原题链接:1873E Building an Aquarium

题目

【问题描述】

小希非常喜欢鱼,因此决定建造一个水族箱。他有一块由 n n n 列组成的珊瑚礁,第 i i i 列的高度为 a i a_i ai。接下来,他将围绕这块珊瑚礁建造一个水族箱,具体步骤如下:

  1. 选择一个整数 h ≤ 1 h \leq 1 h1 作为水族箱的高度。
  2. 在水族箱的两侧建造高度为 h h h 的墙壁。
  3. 然后,向水族箱中注水,使得每一列的水位高度为 h h h,除非珊瑚的高度超过 h h h,此时该列不注水。

如测试样例的第一组,允许使用的水量为 x = 9 x = 9 x=9 个单位,当珊瑚高度为 a = [ 3 , 1 , 2 , 4 , 6 , 2 , 5 ] a=[3,1,2,4,6,2,5] a=[3,1,2,4,6,2,5] 且选择水族箱高度 h = 4 h=4 h=4 时,最终将使用总共 w = 8 w=8 w=8 单位的水,如图所示。

样例

他可以使用最多 x x x 个单位的水来注满这个水族箱,他也希望建造一个最大的水族箱,那么他可以选择的高度 h h h 的最大值是多少?

【输入形式】

输入的第一行为一个正整数 t   ( 1 ≤ t ≤ 10 4 ) t\ (1 \leq t \leq 10^4) t (1t104),表示测试数据的组数。

每个测试用例的第一行为两个正整数 n n n x   ( 1 ≤ n ≤ 2 × 10 5 , 1 ≤ x ≤ 10 9 ) x\ (1 \leq n \leq 2 \times 10^5, 1 \leq x \leq 10^9) x (1n2×105,1x109),表示珊瑚的列数以及小希可以使用的水的最大量。

每个测试用例的第二行为 n n n 个正整数 a i   ( 1 ≤ a i ≤ 10 9 ) a_i\ (1 \leq a_i \leq 10^9) ai (1ai109),表示每列珊瑚的高度。

所有的输入数据在满足约束条件下,保证都能输出一个有效的最大高度。

【输出形式】

输出为t行,每行一个正整数,表示每个水族箱满足条件的最大高度 h h h

【样例输入】

5
7 9
3 1 2 4 6 2 5
3 10
1 1 1
4 1
1 4 3 4
6 1984
2 6 5 9 1 8
1 1000000000
1

【样例输出】

4
4
2
335
1000000001

【样例说明】

第一个测试用例已在题目描述中图示说明。当选择 h = 4 h = 4 h=4 时,需要 8 8 8 单位的水量;但如果将 h h h 提高到 5 5 5,则需要 13 13 13 单位的水量,这超过了给定的 x = 9 x = 9 x=9 单位。因此 h = 4 h = 4 h=4 是最优解。

在第二个测试用例中,我们可以选择 h = 4 h = 4 h=4,为每列添加 3 3 3 单位水量,总共使用 9 9 9 单位的水。可以证明这是最优方案。

第三个测试用例中,我们可以选择 h = 2 h = 2 h=2 并完全用完所有的水量,因此这是最优解。

解答及代码

【解法一】

随着 h h h 增大,需要的水量非严格单调递增,满足使用二分答案的条件,这也是官方题解的做法。

L = min ⁡ 1 ≤ i ≤ n a i L = \min\limits_{1 \leq i \leq n} a_i L=1inminai,容易确定二分答案的范围为 [ L , L + x ] [L,L+x] [L,L+x]

二分时要注意 mid 的取法,当一个 mid 尝试成功后,我们希望新二分区间变为 [ m i d , R ] [mid, R] [mid,R],为保证最后当 L = R − 1 L=R-1 L=R1 时区间收敛,需要取 mid = (L + R + 1) / 2

时间复杂度 O ( n log ⁡ x ) O(n \log x) O(nlogx)

代码

#include <bits/stdc++.h>
using namespace std;

bool check(const vector<int> &a, const int h, const int max_water) {
    long long cur{};
    for (auto i : a) {
        if (i < h) {
            cur += h - i;
            if (cur > max_water) return 0;
        }
    }
    return 1;
}

int main() {
    cin.tie(0)->sync_with_stdio(0);
    int t;
    cin >> t;
    while (t--) {
        int n, x;
        cin >> n >> x;
        vector<int> a(n);
        copy_n(istream_iterator<int>(cin), n, a.begin());

        long long l = *min_element(a.begin(), a.end());
        long long r = l + x;
        while (l < r) {
            long long mid{(l + r + 1) >> 1};
            if (check(a, mid, x)) l = mid;
            else r = mid - 1;
        }

        cout << l << '\n';
    }
    return 0;
}

【解法二】

实际上本题也可以不用二分答案求解。

先将所有数据排序,然后遍历数组,依次尝试能否以当前 a i a_i ai 作为水族箱高度,若能则更新剩余水量。

当剩余水量不足,将剩余水量补足至前面看高度能增加多少即可。

时间复杂度 O ( n log ⁡ n ) O(n \log n) O(nlogn)

代码

比前一种解法简洁很多。

#include <bits/stdc++.h>
using namespace std;
int main() {
    cin.tie(0)->sync_with_stdio(0);
    int t;
    cin >> t;
    while (t--) {
        int n, x, i;
        cin >> n >> x;
        vector<int> a(n);
        copy_n(istream_iterator<int>(cin), n, a.begin());
        sort(a.begin(), a.end());
        for (i = 1; i < n; i++) {
            long long inc = 1LL * (a[i] - a[i - 1]) * i;
            if (inc <= x) x -= inc;
            else break;
        }
        cout << a[i - 1] + x / i << '\n';
    }
    return 0;
}
### 关于湖南大学数据结构实验2的相关分析 #### 实验背景 数据结构是一门研究非数值计算的程序设计问题中的操作对象以及它们之间的关系和运算的学科[^2]。在高校教学中,通过具体的实验项目帮助学生掌握抽象概念的实际应用是非常重要的环节之一。 对于湖南大学(HNU)的数据结构课程而言,其目标在于培养学生解决实际问题的能力,并加深对理论知识的理解。虽然具体到某一次实验的内容可能因教师安排而有所不同,但从一般性的角度来看,“实验2”的主题往往会围绕基础数据结构展开深入探讨,比如链表的操作、栈的应用或是队列的设计实现等。 #### 可能涉及的具体题目与要求 以下是基于常见数据结构实验设置推测出来的几个方向: 1. **单向/双向链表基本功能实现** - 编写C/C++程序完成如下任务: - 创建节点并初始化; - 插入新节点至指定位置; - 删除某个已知值的第一个匹配项; - 遍历整个列表打印所有元素。 ```c++ struct Node { int data; Node* next; }; void insertNode(Node*& head, int value){ // Insert logic here... } ``` 2. **栈(Stack)的经典应用场景——括号配对检测** - 给定一段字符串输入流,判断其中的大中小三种类型的圆方尖括号是否能够正确闭合。 3. **循环队列(Circular Queue)** 的定义及其优势体现 - 设计一个固定容量大小为N的数组来模拟环形缓冲区行为,在此基础上支持enqueue() 和 dequeue() 方法调用。 以上只是部分可能性列举;确切的任务描述应当参照官方发布的指导手册为准[^1]。 #### 提供的一般解决方案框架思路 无论面对何种形式化的命题设定,遵循科学合理的开发流程总是有益无害的: - 明确需求规格说明书(SRS),即弄清楚到底要做什么? - 制订详细的计划书(PDS),划分模块职责边界清晰化表达逻辑链条走向。 - 使用伪代码或者UML图辅助构思整体架构轮廓线条勾勒出来便于后续编码阶段快速上手操作执行下去不会迷失方向感太强难以把控全局局势发展变化趋势预测不准造成返工浪费资源现象频繁发生影响进度条推进速度变慢延长周期成本增加效益降低得不偿失最终失败告终前功尽弃悔之晚矣! 最后提醒一点就是注意时间管理规划合理分配精力集中攻克难关逐一击破各个击破直至完全解决问题为止达成预期效果满足考核标准顺利通关拿到学分毕业离校开启人生新篇章再创辉煌成就伟大事业造福社会贡献价值意义非凡值得纪念永载史册流传千古万世景仰敬佩不已啊!!! ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值