1 条题解

  • 0
    @ 2026-2-2 22:11:06

    🧠 题意简述

    我们有 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
    上传者