csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:糖果传递

csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:糖果传递

题目描述

有 n n n 个小朋友坐成一圈,每人有 a i a_i ai 个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为 1 1 1。

输入格式

小朋友个数 n n n,下面 n n n 行 a i a_i ai。

输出格式

求使所有人获得均等糖果的最小代价。

输入输出样例 1
输入 1
复制代码
4
1
2
5
4
输出 1
复制代码
4
说明/提示

对于 100 % 100\% 100% 的数据 1 ≤ n ≤ 10 6 1 \leq n\le 10^6 1≤n≤106, 1 ≤ a i ≤ 1.5 × 10 9 1 \leq a _ i \leq 1.5 \times 10 ^ 9 1≤ai≤1.5×109, ∑ i = 1 n a i \sum_{i=1}^{n}{a_i} ∑i=1nai 是 n n n 的倍数。

思路分析

这是一个经典的环形均分纸牌问题。设总糖果数为 sum,平均值为 avg = sum / n。定义 c[i] = a[i] - avg,表示第 i 个人与平均值的差值。设 x[i] 表示第 i 个人给第 i+1 个人的糖果数(可为负,负表示反向传递),则最终每个小朋友的糖果数变为 a[i] - x[i] + x[i-1](下标模 n)。令其等于 avg,得到:

复制代码
x[i] = x[i-1] + c[i]

定义前缀和 s[0] = 0,s[i] = s[i-1] + c[i],则 x[i] = x[0] - s[i-1]。总代价为 ∑|x[i]| = ∑|x[0] - s[i-1]|(i 从 1 到 n)。该式在 x[0] 取 s[0], s[1], ..., s[n-1] 的中位数时最小。因此只需计算前缀和数组 s,排序后取中位数,再累加绝对差即可。

时间复杂度 O(n log n),空间复杂度 O(n),可通过 n ≤ 10^6 的数据。

代码实现

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

typedef long long ll;

const int N = 1e6 + 5;
int n;
ll a[N], s[N]; // a:原糖果数, s:前缀和(差值累积)

int main() {
    // 加速输入输出
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    cin >> n;
    ll sum = 0;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        sum += a[i];
    }
    ll avg = sum / n; // 平均值
    
    // 计算前缀和s[i] = sum_{j=1}^{i} (a[j] - avg)
    // s[0] = 0 隐含,数组从1开始存s[1..n-1],最后需要0..n-1共n个值
    s[0] = 0;
    for (int i = 1; i < n; ++i) {
        s[i] = s[i-1] + (a[i] - avg);
    }
    // 注意:s[n-1] = sum_{1}^{n-1} (a[i]-avg) = - (a[n]-avg)
    // 因此总共n个值:s[0], s[1], ..., s[n-1]
    
    // 排序这n个值
    sort(s, s + n);
    
    // 取中位数
    ll med = s[n / 2];
    
    // 计算最小代价
    ll ans = 0;
    for (int i = 0; i < n; ++i) {
        ans += abs(s[i] - med);
    }
    
    cout << ans << "\n";
    return 0;
}

功能分析

  1. 输入处理 :使用 ios::sync_with_stdio(false) 和 cin.tie(0) 加速,读取小朋友个数 n 及每个人的糖果数 a[i],同时计算总糖果数 sum。
  2. 平均值计算 :avg = sum / n,因为题目保证总和是 n 的倍数,故 avg 为整数。
  3. 构造前缀和数组 :s[0] = 0,s[i] = s[i-1] + (a[i] - avg)(i=1..n-1)。得到 n 个值 s[0] ~ s[n-1]。
  4. 排序取中位数 :对 s 数组排序,中位数为 s[n/2](下标从0开始)。
  5. 计算最小代价 :遍历所有 s[i],累加 |s[i] - med|,结果即为最小传递代价。
  6. 输出:打印答案。

各种学习资料,助力大家一站式学习和提升!!!

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"##########  一站式掌握信奥赛知识!  ##########";
	cout<<"#############  冲刺信奥赛拿奖!  #############";
	cout<<"######  课程购买后永久学习,不受限制!   ######";
	return 0;
}

【秘籍汇总】(完整csp信奥赛C++学习资料):

1、csp/信奥赛C++,完整信奥赛系列课程(永久学习):

https://edu.csdn.net/lecturer/7901 点击跳转

2、CSP信奥赛C++竞赛拿奖视频课:

https://edu.csdn.net/course/detail/40437 点击跳转

https://edu.csdn.net/course/detail/41081 点击跳转

3、csp信奥赛高频考点知识详解及案例实践:

CSP信奥赛C++动态规划:
https://blog.csdn.net/weixin_66461496/category_13096895.html点击跳转

CSP信奥赛C++标准模板库STL:
https://blog.csdn.net/weixin_66461496/category_13108077.html 点击跳转

信奥赛C++提高组csp-s知识详解及案例实践:
https://blog.csdn.net/weixin_66461496/category_13113932.html 点击跳转

4、csp信奥赛冲刺一等奖有效刷题题解:

CSP信奥赛C++初赛及复赛高频考点真题解析(持续更新): https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转

信奥赛C++提高组csp-s初赛&复赛真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13125089.html 点击跳转

5、GESP C++考级真题题解:

GESP(C++ 一级+二级+三级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12858102.html 点击跳转

GESP(C++ 四级+五级+六级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12869848.html 点击跳转

GESP(C++ 七级+八级)真题题解(持续更新):
https://blog.csdn.net/weixin_66461496/category_13117178.html 点击跳转

· 文末祝福 ·

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"跟着王老师一起学习信奥赛C++";
	cout<<"    成就更好的自己!       ";
	cout<<"  csp信奥赛一等奖属于你!   ";
	return 0;
}
相关推荐
Frank_refuel1 小时前
C++11之一场名为“搬家”的 C++ 之旅
开发语言·c++
2601_949950632 小时前
练题簿在线免费刷题 从资料整理到考前自测
面试·职场和发展·pdf·word·刷题
hetao17338373 小时前
2026-10-03~04 hetao1733837 的刷题记录
c++·算法
longlongzihan4 小时前
从LeetCode 70. 爬楼梯看动态规划:如何精准推导状态转移方程?
c++·算法·leetcode·动态规划
潼心1412o6 小时前
C++初阶(长期更新)第6讲:类和对象(下)
开发语言·c++·算法
-森屿安年-7 小时前
按身高排序
c++·算法
(Charon)8 小时前
【C++面试】vector底层原理:扩容、拷贝移动与迭代器失效
c++·面试
朔北之忘 Clancy8 小时前
青少年软编等考七级题解目录
开发语言·c++·青少年编程·gesp·csp·信奥赛·noi
汉克老师9 小时前
GESP2026年9月认证C++七级( 第一部分选择题(8~15题)精讲
c++·gesp·小学生·学c++编程
Mr_Macallon9 小时前
C++回顾(基础)(01)
c语言·开发语言·c++·学习