题解:学而思编程 元素分类

【题目来源】

学而思编程:元素分类

【题目描述】

给定 \(n\) 个整数元素 \(x_i\)。现在,需要你对这 \(n\) 个整数元素进行分类。

每个元素要么划分至 \(b\) 类,要么划分至 \(c\) 类。

我们设所有 \(b\) 类元素的相加之和为 \(sum_b\),所有 \(c\) 类元素的相加之和为 \(sum_c\)

请你计算 \(sum_b−sum_c\) 的最大可能值。

如果某类元素的个数为 \(0\),则该类元素的相加之和视为 \(0\)

【输入】

第一行包含整数 \(n\)

第二行包含 \(n\) 个整数 \(x_i\)

【输出】

输出一个整数,表示 \(sum_b−sum_c\) 的最大可能值。

【输入样例】

3
1 -2 0

【输出样例】

3

【核心思想】

  1. 问题分析:给定 \(n\) 个整数 \(x_i\),每个元素必须分配到 \(b\) 类或 \(c\) 类。设 \(sum_b\)\(b\) 类元素之和,\(sum_c\)\(c\) 类元素之和,求 \(sum_b - sum_c\) 的最大值。这是一个贪心分类问题,关键在于分析每个元素对目标函数的贡献,确定最优分配策略。

  2. 算法选择

    • 贪心策略(Greedy Choice):对每个元素独立决策,使其对 \(sum_b - sum_c\) 的贡献最大化
    • 正负分离:根据元素的符号特征,分别归入不同类别以最大化差值
  3. 关键步骤

    • 初始化\(sum_1 = 0\)(用于累加非负数),\(sum_2 = 0\)(用于累加负数)
    • 遍历元素:对于每个 \(x_i\)
      • \(x_i \ge 0\):归入 \(b\) 类,\(sum_1 \leftarrow sum_1 + x_i\)
        • 选择理由:非负数放入 \(sum_b\) 直接增加差值,放入 \(sum_c\) 会减小差值(或不变)
      • \(x_i < 0\):归入 \(c\) 类,\(sum_2 \leftarrow sum_2 + x_i\)
        • 选择理由:负数放入 \(sum_c\) 时,\(sum_b - sum_c = sum_b - (\text{负数}) = sum_b + |x_i|\),相当于增加差值;若放入 \(sum_b\) 则会减小差值
    • 计算答案\(ans = sum_1 - sum_2\)
      • 由于 \(sum_2\) 为负数,\(sum_1 - sum_2 = sum_1 + |sum_2|\),即所有非负数绝对值之和加上所有负数绝对值之和
    • 输出结果\(ans\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n)\),只需一次遍历所有元素
    • 空间复杂度:\(O(1)\),仅使用 \(sum_1\)\(sum_2\) 两个累加器
  5. 贪心决策的核心思想

    • 独立最优性:每个元素对 \(sum_b - sum_c\) 的贡献只取决于自身分配,与其他元素无关。因此可以逐个独立做最优决策
    • 贡献分析:将 \(x_i\) 放入 \(b\) 类贡献为 \(+x_i\),放入 \(c\) 类贡献为 \(-x_i\)。为使 \(sum_b - sum_c\) 最大,每个元素应选择贡献更大的方向:
      • \(x_i \ge 0\)\(+x_i \ge -x_i\),选 \(b\)
      • \(x_i < 0\)\(-x_i > +x_i\)(负数的相反数为正),选 \(c\)
    • 全局最优性:局部最优决策的累加即为全局最优,无后效性和冲突性
    • 零的特殊处理\(x_i = 0\) 时放入任一类贡献均为 \(0\),归入 \(sum_1\) 不影响结果
    • 适用于每个元素独立贡献、无交叉约束的最大化/最小化分配问题

【算法标签】

模拟

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int n, sum1, sum2;  // sum1: 正数和, sum2: 负数和

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        int num;
        cin >> num;
        // 根据正负分别累加
        if (num >= 0)
        {
            sum1 += num;  // 累加正数
        }
        else
        {
            sum2 += num;  // 累加负数
        }
    }
    // 输出正数和减去负数和
    cout << sum1 - sum2 << endl;
    return 0;
}

【运行结果】

3
1 -2 0
3
posted @ 2026-07-05 16:07  团爸讲算法  阅读(4)  评论(0)    收藏  举报