题解:AtCoder AT_awc0034_c Watering the Flower Bed
【题目来源】
AtCoder:C - Watering the Flower Bed
【题目描述】
Takahashi manages \(N\) flower beds arranged in a row in his garden. The flower beds are numbered \(1, 2, \ldots, N\) from left to right, and the current moisture level of the soil in flower bed \(i\) (\(1 \leq i \leq N\)) is \(A_i\).
高桥在他的花园中管理着一排 \(N\) 个花坛。花坛从左到右编号为 \(1, 2, \ldots, N\),花坛 \(i\)(\(1 \leq i \leq N\))土壤当前的湿度水平为 \(A_i\)。
Since he will have guests tomorrow, Takahashi wants to make all flower beds have a moisture level of at least the target value \(T\) so that the flowers bloom beautifully. It is fine if the moisture level exceeds \(T\).
由于明天将有客人来访,高桥希望所有花坛的湿度水平至少达到目标值 \(T\),以便花朵美丽绽放。湿度水平超过 \(T\) 也可以。
Takahashi can perform the following operation any number of times (possibly \(0\) times):
高桥可以执行任意次(包括 \(0\) 次)以下操作:
- Operation: Choose an integer \(l\) satisfying \(1 \leq l \leq N - K + 1\), and water the \(K\) consecutive flower beds from flower bed \(l\) to flower bed \(l + K - 1\) using a sprinkler. This increases the moisture level of each of those \(K\) flower beds by \(1\). Each operation costs \(C\) yen in water charges.
操作:选择一个满足 \(1 \leq l \leq N - K + 1\) 的整数 \(l\),并使用洒水器为从花坛 \(l\) 到花坛 \(l + K - 1\) 的 \(K\) 个连续花坛浇水。这会将这 \(K\) 个花坛的湿度水平各提高 \(1\)。每次操作的水费为 \(C\) 日元。
The value of \(l\) chosen in each operation is arbitrary, and the same value of \(l\) may be chosen in different operations.
每次操作所选的 \(l\) 值可以任意,且在不同操作中可以选择相同的 \(l\) 值。
Find the minimum total water cost (in yen) required to make the moisture level of all flower beds at least \(T\).
求使所有花坛的湿度水平至少达到 \(T\) 所需的最小总水费(以日元计)。
【输入】
\(N\) \(K\) \(T\) \(C\)
\(A_1\) \(A_2\) \(\cdots\) \(A_N\)
- The first line contains the number of flower beds \(N\), the number of flower beds watered simultaneously by the sprinkler \(K\), the target moisture level \(T\), and the water cost per operation \(C\) (yen), separated by spaces.
- The second line contains the initial moisture levels of each flower bed \(A_1, A_2, \ldots, A_N\), separated by spaces.
【输出】
Print the minimum total water cost (in yen) required to make the moisture level of all flower beds at least \(T\), as an integer on a single line.
【输入样例】
5 3 10 100
8 7 9 12 11
【输出样例】
300
【核心思想】
-
问题分析:给定 \(N\) 个花坛的初始湿度 \(A_i\),每次操作可以将连续 \(K\) 个花坛的湿度各加 \(1\),花费 \(C\) 日元。目标是使所有花坛湿度至少达到 \(T\),求最小总花费。这是一个差分数组 + 贪心问题,关键在于如何确定每个位置需要操作多少次。
-
算法选择:
- 差分数组(Imos 法):用差分数组记录区间加法操作的影响,高效维护当前累计增加值
- 贪心策略:从左到右遍历,遇到湿度不足的花坛就在该位置尽可能多地执行操作(贪心选择),确保前面的花坛不再被影响
- 实时计算需求:根据当前累计值和初始值,计算每个位置还需要增加多少
-
关键步骤:
- 初始化:
cur = 0(当前累计增加值),imos[]为差分数组 - 从左到右贪心遍历(\(i\) 从 \(1\) 到 \(N\)):
- 更新当前累计值:
cur += imos[i],表示位置 \(i\) 被前面操作影响后的总增加值 - 计算当前湿度:
current = a[i] + cur - 判断是否需要操作:
- 若
current >= T:湿度已达标,跳过 - 若
current < T:湿度不足,需要操作- 计算需求:
need = T - current,表示需要在位置 \(i\) 执行need次操作 - 累加操作次数:
ans += need - 更新差分数组:若 \(i + K \leq N\),则
imos[i + K] -= need(在位置 \(i+K\) 处结束影响) - 更新累计值:
cur += need
- 计算需求:
- 若
- 更新当前累计值:
- 输出总花费
ans * C
- 初始化:
-
时间/空间复杂度:
- 时间复杂度:\(O(N)\),遍历数组一次,每次操作 \(O(1)\)
- 空间复杂度:\(O(N)\),差分数组空间
-
差分数组与贪心的核心思想:
- 区间操作降维:差分数组将区间 \([i, i+K-1]\) 的加
need操作转化为imos[i] += need和imos[i+K] -= need - 贪心最优性:从左到右贪心操作是最优的,因为每个位置一旦被处理就不会再被访问,且必须在当前位置执行足够操作才能达标
- 实时维护累计值:用变量
cur维护当前位置的累计增加值,避免重复计算 - 延迟更新技巧:通过
imos[i+K] -= need实现区间影响的自动结束 - 适用于区间加法、资源分配、贪心决策类问题
- 区间操作降维:差分数组将区间 \([i, i+K-1]\) 的加
【算法标签】
差分
【代码详解】
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;
int n, k, t, c, ans; // n: 数组长度, k: 影响范围, t: 目标值, c: 单位代价, ans: 操作次数
int a[N], imos[N], cur; // a: 原始数组, imos: 差分数组, cur: 当前累计增加值
signed main()
{
cin >> n >> k >> t >> c; // 输入参数
for (int i = 1; i <= n; i++)
{
cin >> a[i]; // 输入原始数组
}
for (int i = 1; i <= n; i++) // 遍历每个位置
{
cur += imos[i]; // 更新当前位置的累计增加值
if (a[i] + cur < t) // 如果当前值小于目标值
{
int need = t - (a[i] + cur); // 计算需要增加的值
ans += need; // 累计操作次数
if (i + k <= n) // 如果影响范围未超出数组
{
imos[i + k] -= need; // 在差分数组记录减少
}
cur += need; // 当前累计值增加
}
}
cout << ans * c << endl; // 输出总代价
return 0;
}
【运行结果】
5 3 10 100
8 7 9 12 11
300
浙公网安备 33010602011771号