OJ3260最大数组和问题

题目:

小明是一名勇敢的冒险家,他在一次探险途中发现了一组神秘的宝石,这些宝石的价值都不同。但是,他发现这些宝石会随着时间的推移逐渐失去价值,因此他必须在规定的次数内对它们进行处理。 小明想要最大化这些宝石的总价值。他有两种处理方式:

1.选出两个最小的宝石,并将它们从宝石组中删除。

2.选出最大的宝石,并将其从宝石组中删除。 现在,给你小明手上的宝石组,请你告诉他在规定的次数内,最大化宝石的总价值是多少。

输入格式 第一行包含一个整数t,表示数据组数。 对于每组数据,第一行包含两个整数n和k,表示宝石的数量和规定的处理次数。

第二行包含n个整数a1,a2,...,an,表示每个宝石的价值。 输出格式 对于每组数据,输出一个整数,表示在规定的次数内,最大化宝石的总价值。

思路:

首先,对原始数组进行排序不会影响结果,因为最小宝石始终在数组的开头,最大宝石则在数组的未尾。也就是排序后,每次操作要么删除左边的两个元素,要么删除右边的一个元素。因此,如果我们删除2m 个最小宝石和(k-m)个最大宝石,则剩余的元素组成的段在排序后的数组中从位置(2m + 1)到位置(n-(k-m)),可以从左到右遍历 ,使用前缀和在 O(1)时间内计算其总和。

样例输入

cpp 复制代码
6
5 1
2 5 1 10 6
5 2
2 5 1 10 6
3 1
1 2 3
6 1
15 22 12 10 13 11
6 2
15 22 12 10 13 11
5 1
999999996 999999999 999999997 999999998 999999995

样例输出

cpp 复制代码
21
11
3
62
46
3999999986

代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
    int t;
    cin >> t; // 读取测试用例的数量
    while(t--) { // 对每一个测试用例进行处理
        int n, k;
        cin >> n >> k; // 读取宝石的数量n和处理次数k
        vector<ll> a(n), sum(n + 1, 0); // 初始化数组a用于存放宝石价值,sum用于存放前缀和
        for(int i = 0; i < n; i++) cin >> a[i]; // 读取宝石价值数组
        
        sort(a.begin(), a.end()); // 将宝石价值按从小到大排序
        
        // 计算前缀和数组
        for(int i = 1; i <= n; i++) {
            sum[i] = sum[i - 1] + a[i - 1];
        }
        
        ll ans = 0; // 用于存放最大价值和
        
        // 遍历可能的删除组合
        for(int m = 0; m <= k; m++) {
            if(2 * m <= n && (k - m) <= n - 2 * m) {
                ll current_sum = sum[n - (k - m)] - sum[2 * m];
                ans = max(ans, current_sum);//表示删除这些宝石后的总和。
            }
        }
        
        cout << ans << "\n"; // 输出结果
    }
    return 0;
}

详细过程解释

  1. 输入读取

    • 读取测试用例的数量 t
  2. 处理每个测试用例

    • 读取宝石的数量 n 和处理次数 k
    • 初始化一个大小为 n 的数组 a,用于存储每个宝石的价值。
    • 初始化一个大小为 n + 1 的数组 sum,用于存储前缀和,初始值为 0。
    • 读取宝石价值,存入数组 a
    • 对数组 a 进行排序,以便后续操作方便。
    • 计算前缀和 sumsum[i] 表示数组 a 中前 i 个元素的和。
  3. 遍历可能的删除组合

    • 遍历 m 从 0 到 k,表示删除 2m 个最小宝石和 (k - m) 个最大宝石。
    • 对于每个 m,计算删除后的剩余元素的和:
      • sum[n - (k - m)] 表示删除 k - m 个最大宝石后,剩余元素的和。
      • sum[2 * m] 表示删除 2m 个最小宝石后的和。
      • current_sum = sum[n - (k - m)] - sum[2 * m] 表示删除这些宝石后的总和。
    • 更新 ans 为当前情况下的最大和。
  4. 输出结果

    • 在每个测试用例处理完成后,输出 ans

这样,通过逐步删除最小宝石和最大宝石,并计算剩余元素的和,我们可以找到在规定次数内最大化宝石总价值的方法。

相关推荐
Indigo_code1 小时前
【数据结构】【顺序表算法】 删除特定值
数据结构·算法
麻辣韭菜2 小时前
网络基础 【HTTP】
网络·c++·http
阿史大杯茶2 小时前
Codeforces Round 976 (Div. 2 ABCDE题)视频讲解
数据结构·c++·算法
LluckyYH2 小时前
代码随想录Day 58|拓扑排序、dijkstra算法精讲,题目:软件构建、参加科学大会
算法·深度优先·动态规划·软件构建·图论·dfs
转调2 小时前
每日一练:地下城游戏
开发语言·c++·算法·leetcode
不穿格子衬衫3 小时前
常用排序算法(下)
c语言·开发语言·数据结构·算法·排序算法·八大排序
wdxylb3 小时前
使用C++的OpenSSL 库实现 AES 加密和解密文件
开发语言·c++·算法
aqua35357423583 小时前
蓝桥杯-财务管理
java·c语言·数据结构·算法
CV金科3 小时前
蓝桥杯—STM32G431RBT6(IIC通信--EEPROM(AT24C02)存储器进行通信)
stm32·单片机·嵌入式硬件·算法·蓝桥杯
sewinger3 小时前
区间合并算法详解
算法