P3817 小A的糖果

P3817 小A的糖果

https://www.luogu.org/problemnew/show/P3817

心得:

1. 重新定义long long 类型,使用方便,不用反复写长代码 typedef long long ll;

2. 定义常量:const int N = 100000002;

#include<iostream>
using namespace std;
typedef long long ll;	//重新定义long long类型为 ll 
const int N = 100000002; 
ll n=0,x,a[N],s=0; 
int main()
{
	cin>>n>>x;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
	}
	//处理第0项
	if(a[0]>x)
	{
		s = a[0]-x;
		a[0] = x;
	} 
	//重新再处理一次所有向,两项数据一组 
	ll t = 0;
	for(int i=1;i<n;i++)
	{
		t = a[i-1]+a[i]-x;
		if(t>0)
		{
			s += t;
			a[i] = x-a[i-1];
		}
	}
	cout<<s<<endl;
	return 0;
}

 

<think>根据用户需求,我需要查找洛谷P3817题目的详细信息。从提供的引用内容中,我找到了关于该题目的多个信息片段。 引用[1]提供了P3817题解的核心代码和思路,明确说明这是"小A的糖果"题目,使用贪心思想解决。代码采用C++实现,主要逻辑是遍历数组,当相邻两数之和超过给定值m时,调整后一个元素的值并记录需要减去的糖果总数。 引用[2]进一步确认了题目名称"小A的糖果",并给出了题目描述的关键信息:输入格式包含n和m,输出格式要求一个整数答案。同时提到数据规模为10^5量级,需要注意算法效率。 引用[3]提到初解存在超时问题,说明题目对时间复杂度有要求,并给出了优化思路的提示——避免使用while循环嵌套,应使用单次遍历的O(n)解法。 引用[4]提供了另一种C语言实现的代码,逻辑与引用[1]类似但处理边界略有不同,同样验证了题目核心要求是调整相邻元素和不超过x。 综合所有引用,可以完整还原题目如下: 题目名称:小A的糖果 题目描述:给定n个糖果盒排成一列,每个盒子有a[i]颗糖果。要求任意相邻两盒糖果总数不超过x。每次操作可以减少某盒的糖果数,求最少需要吃掉多少糖果。 输入:第一行n和x,第二行n个整数表示每盒糖果数 输出:一个整数表示最少吃掉的糖果数 数据范围:n ≤ 10^5, 其他数在int范围内 注意点:必须使用O(n)贪心算法,若使用双重循环会超时</think>### 洛谷 P3817 题目详情:小A的糖果 #### 题目描述 小A有 $n$ 个糖果盒排成一列,每个盒子有 $a_i$ 颗糖果。他要求任意相邻两盒的糖果总数 **不能超过** 给定值 $x$。若不符合条件,小A可以吃掉某些盒子中的糖果。求最少需要吃掉多少颗糖果才能满足要求。 #### 输入格式 - 第一行:两个整数 $n$ 和 $x$($1 \leq n \leq 10^5$, $0 \leq x \leq 10^9$)。 - 第二行:$n$ 个整数 $a_0, a_1, \dots, a_{n-1}$($0 \leq a_i \leq 10^9$),表示每盒的初始糖果数。 #### 输出格式 - 一个整数,表示最少吃掉的糖果总数。 #### 输入输出样例 **样例 1:** 输入: ``` 3 3 2 2 2 ``` 输出: ``` 1 ``` **解释:** 调整后糖果序列可为 $[2,1,2]$,吃掉 $1$ 颗糖果(第二盒减少 $1$ 颗)[^1][^2]。 **样例 2:** 输入: ``` 6 1 1 6 1 2 0 4 ``` 输出: ``` 11 ``` #### 核心算法:贪心思想 1. **从左向右遍历**:从第 $1$ 个盒子($i=0$)开始,检查相邻两盒 $a_i$ 和 $a_{i+1}$ 之和是否 $> x$。 2. **调整策略**: - 若 $a_i + a_{i+1} > x$,则需减少 $a_{i+1}$ 的糖果(因为修改右侧对后续影响更小)。 - 吃掉糖果数 $= (a_i + a_{i+1} - x)$,同时更新 $a_{i+1} = x - a_i$。 3. **累加结果**:将每次吃掉的糖果数累加即为答案。 #### 参考代码(C++,$O(n)$ 复杂度) ```cpp #include <iostream> using namespace std; long long n, x, ans; // 注意数据范围,需用 long long int main() { cin >> n >> x; long long a[n]; for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i < n - 1; i++) { long long sum = a[i] + a[i + 1]; if (sum > x) { ans += sum - x; // 累加吃掉的糖果 a[i + 1] = x - a[i]; // 修改后一盒的糖果数 } } cout << ans; return 0; } ``` **关键点**: - **贪心正确性**:优先修改右侧盒子,避免重复调整(左侧已满足条件)。 - **复杂度**:单次遍历 $O(n)$,适用于 $n \leq 10^5$ 的数据规模[^1][^3][^4]。 - **边界**:若 $x$ 极大(如 $x \geq 2 \times 10^9$),无需调整;若 $x=0$,则所有糖果需清零。 #### 常见错误 - **超时问题**:若用嵌套循环(如 `while` 逐颗减少),时间复杂度退化为 $O(n^2)$,导致超时[^3]。 - **数据溢出**:未使用 `long long` 存储累加值($ans$ 可能超过 $10^{10}$)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

二中卢老师

创作不易,你的鼓励是我最大的动

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

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

打赏作者

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

抵扣说明:

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

余额充值