1. 贝茜的操作是合并相邻蛋糕到最后一个蛋糕,相当于埃尔茜吃完固定次数后剩余的蛋糕总和。
2. 埃尔茜的操作是拿走最左或最右的蛋糕,这类似于从数组的两端取数。
最优策略下贝茜所堆叠的蛋糕都不会让给另一个牛吃,从而埃尔茜仅会吃到原始数组元素大小的蛋糕份额。
(不会吃到堆叠的蛋糕【吃到就相当于让埃尔茜多吃了一个 不符合最优策略】)
由此我们得到了两头奶牛的最优策略:
1. 贝茜的最优策略是在埃尔茜左右吃蛋糕时候,不让其吃到自己堆叠好的蛋糕。
2. 埃尔茜的最优策略是在左右吃原始份额的蛋糕,吃到最大份额的蛋糕。
因此我们将问题指向求埃尔茜吃到的最大份额蛋糕,而因为其左右吃的特性,我们可以将问题转化为求
数组总和 - 定长子数组的之和的最小值(相当于求出从数组的两端取数的最大之和)。
这样就是埃尔茜吃到的最大份额蛋糕,由于题目限制最后一个蛋糕结束,易得贝茜吃掉的蛋糕数目为 n / 2 + 1
,就可以去求长度为 n / 2 + 1
的定长子数组的之和的最小值(定长滑动窗口)。
最后答案:
贝茜:定长子数组的之和的最小值
埃尔茜:数组总和 - 定长子数组的之和的最小值
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve() {
int n;
cin >> n;
vector<int> a(n);
for (int& x : a)
cin >> x;
// 计算窗口长度,n/2 + 1
int len = n / 2 + 1;
ll total = 0; // 当前窗口的和
ll res = LONG_LONG_MAX; // 最小窗口和,初始为最大值
ll sum = 0; // 数组总和
for (int i = 0; i < n; ++i) {
sum += a[i]; // 累加数组总和
// 前len个元素直接累加
if (i < len) {
total += a[i];
// 当窗口第一次填满时,更新res
if (i == len - 1)
res = min(res, total);
continue;
}
// 滑动窗口:减去左边界的元素,加上右边界的元素
total -= a[i - len];
total += a[i];
res = min(res, total); // 更新最小窗口和
}
// 输出最小窗口和以及剩余部分的和
cout << res << ' ' << sum - res << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int t = 1;
cin >> t;
while (t--)
solve();
return 0;
}
哇塞,你这个解释才是正确的吧,其它的解释都看着怪怪的,本来贝茜最优的情况下就是不让埃尔茜吃到堆叠过的元素,所以埃尔茜埃尔茜仅会吃到原始数组元素大小,大佬牛逼