题解:P14796 [JOI 2026 二次预选] 究极团子达人 / Ultimate Dango Maker
William_Y1 · · 题解
原题传送门
题意
每三个元素
思路
明显,如果
具体来说,只能是
那么我们就想到了一个很好的贪心(凡是叫不出来的都是贪心):先把
具体来讲,对于所有
参考代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 201000;
int n, a[N];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
ll ans = 0;
for (int i = 1; i <= n; i++)
ans += a[i] / 3, a[i] %= 3; // 同色讨论
for (int i = 1; i <= n - 1; i++) {
if (a[i] + a[i + 1] >= 3)
ans++, a[i + 1] += a[i] - 3; // 相邻颜色的讨论,然后 a[i] 可以不清零,因为用不到了
}
printf("%lld", ans);
}
预计得分 42pts。
为什么?
让我们看看这个:
3
2 3 1
我们的代码会先把
这意味着我们的贪心假了……
反思一下,既然直接取模会破坏与两侧的联系,那么先把前面的处理掉再取模不就好了?
于是代码就有了。
AC Code(c++)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 201000;
int n, a[N];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
ll ans = 0;
for (int i = 1; i <= n - 1; i++) {
ans += a[i] / 3; // 此时取模不会对左侧产生影响,因为已经讨论过了,之后会再讨论右侧
a[i] %= 3;
if (a[i] + a[i + 1] >= 3)
ans++, a[i + 1] += a[i] - 3; // 讨论
}
ans += a[n] / 3;
a[n] %= 3; // a[n] 别忘了
printf("%lld", ans);
}