1 条题解
-
0
🧠 题意简述
我们有 N 个牛栏,每个牛栏当前温度是 t[i],奶牛希望的温度是 p[i]。
空调每次操作可以选择任意一个连续区间 [L, R],将这个区间内所有牛栏的温度 统一 +1 或 -1。目标:用最少的操作次数,使得每个牛栏最终温度等于对应奶牛的理想温度。
💡 核心思想(差分 + 贪心)
这个问题本质上是一个 区间增减问题,可以用 差分数组 的思想高效解决。
关键观察:
每次操作对一个区间 [L, R] 整体 +1 或 -1,相当于在差分数组上:- 在位置 L 处 +1(或 -1)
- 在位置 R+1 处 -1(或 +1)
但反过来想:如果我们知道每个位置需要变化多少(即 d[i] = p[i] - t[i]),那么最少操作次数就等于 将全零数组通过区间加减变成 d 数组所需的最少操作数。
而这个问题有一个经典结论:
最少操作次数 = 所有正的相邻差分之和 更准确地说,设 d[0] = 0,d[i] = p[i] - t[i],构造差分数组 Δ[i] = d[i] - d[i-1],
则答案就是 Σ max(Δ[i], 0),其中 i 从 1 到 N。或者等价地(如本代码所做):
- 定义 b[i] = p[i] - t[i]
- 补一个 b[0] = 0,b[n+1] = 0
- 答案 = 所有 max(b[i] - b[i-1], 0) 的和(i 从 1 到 n+1)
这其实是在模拟“从左到右构建目标数组”的过程,每次遇到上升(需要增加温度),就必须发起新的操作;下降则可以“复用”之前的降温操作(或不需要新操作)。
#include <bits/stdc++.h> using namespace std; const int MAXN = 100010; // 根据数据范围 N ≤ 100,000 int main() { int n; scanf("%d", &n); int p[MAXN], t[MAXN];// p: 目标温度,t: 当前温度 for (int i = 1; i <= n; i++)scanf("%d", &p[i]);// 读入目标温度 for (int i = 1; i <= n; i++)scanf("%d", &t[i]);// 读入当前温度 // 计算每个牛栏需要的变化量(目标温度 - 当前温度) // 如果是正数表示需要升温,负数表示需要降温 int need[MAXN]; for (int i = 1; i <= n; i++)need[i] = p[i] - t[i]; // 算法核心:计算所有正的相邻差分之和 long long ans = 0; // 假设 need[0] = 0(牛栏0不存在,看作温度为0) // 计算 Δ[i] = need[i] - need[i-1] for (int i = 1; i <= n; i++) { int delta = need[i] - need[i - 1]; // need[0]默认为0 if (delta > 0)ans += delta; // 只累加正的差分 } printf("%lld\n", ans);// 输出结果 return 0; }
- 1
信息
- ID
- 3
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 8
- 已通过
- 2
- 上传者