AtCoder Regular Contest 129 D -1+2-1
挺有趣的题。自己推出来感觉挺有意思的。
首先显然若 \(\sum\limits_{i=0}^{n-1} a_i \ne 0\) 就无解。
设 \(b_i\) 为 \(i\) 的操作次数。可得:
整理得:
发现因为有 \(i - 1\) 和 \(i + 1\) 不好处理。考虑一个通用套路就是设 \(b_i = x_i b_{i-1} + c_i\),得:
整理得:
那么 \(x_i = \frac{1}{2 - x_{i+1}}\),解得 \(\forall i \in [1, n], x_i = 1\)。那么:
得到:
发现 \(b_i\) 是一个类似前缀和的形式,\(b_n - b_0 = \sum\limits_{i=0}^{n-1} c_i - \sum\limits_{i=0}^{n-1} a_i = 0\),所以 \(\sum\limits_{i=0}^{n-1} c_i = 0\)。
设 \(c_0 = c_n = t\),那么 \(i \in [1, n - 1], c_i = t - \sum\limits_{j=i}^{n-1} a_j\),\(c_0 = t\)。因为 \(\sum\limits_{i=0}^{n-1} c_i = 0\),所以 \(t\) 可以解出来,如果 \(t\) 是分数就无解。
那我们现在得到了每个 \(c_i\),剩下的就是求 \(\sum\limits_{i=0}^{n-1} b_i\) 的最小值,并要求 \(b_i = b_{i-1} + c_i, \forall i \in [0, n - 1], b_i \ge 0\)。
设 \(b_0 = k\),那 \(b_i\) 和 \(\sum\limits_{i=0}^{n-1} b_i\) 是关于 \(k\) 的一次函数,并且斜率都为正。因此我们二分最小的 \(k\) 使得 \(\forall i \in [0, n - 1], b_i \ge 0\),得到 \(k\) 后一遍递推即可求出答案。
时间复杂度 \(O(n \log V)\),\(V\) 为值域。
code
// Problem: D - -1+2-1
// Contest: AtCoder - AtCoder Regular Contest 129
// URL: https://atcoder.jp/contests/arc129/tasks/arc129_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
typedef pair<ll, ll> pii;
const int maxn = 200100;
ll n, a[maxn], b[maxn], c[maxn], d[maxn];
inline bool check(ll x) {
b[n - 1] = x;
for (int i = 0; i < n - 1; ++i) {
b[i] = b[(i + n - 1) % n] + c[i];
if (b[i] < 0) {
return 0;
}
}
return 1;
}
void solve() {
scanf("%lld", &n);
ll s = 0;
for (int i = 0; i < n; ++i) {
scanf("%lld", &a[i]);
s += a[i];
}
if (s) {
puts("-1");
return;
}
s = 0;
for (int i = n - 1; ~i; --i) {
c[i] = c[i + 1] - a[i];
s += c[i];
}
if (s % n) {
puts("-1");
return;
}
for (int i = 0; i < n; ++i) {
c[i] -= s / n;
}
ll l = 0, r = 1e12, pos = -1;
while (l <= r) {
ll mid = (l + r) >> 1;
if (check(mid)) {
pos = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
check(pos);
ll ans = 0;
for (int i = 0; i < n; ++i) {
ans += b[i];
}
printf("%lld\n", ans);
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}
/*
-b[i - 1] + 2 * b[i] - b[i + 1] = -a[i]
a[i] + 2 * b[i] = b[i - 1] + b[i + 1]
b[i] = (b[i - 1] + b[i + 1] - a[i]) / 2
b[i - 1] + b[i + 1] 和 a[i] 同奇偶性且 b[i - 1] + b[i + 1] >= a[i]
b[i] = b[i - 1] - a[i] + c[i + 1]
c[i] = c[i + 1] - a[i]
c[n - 1] = c[0] - a[i]
b[n] = c[1] - a[1] + c[2] - a[2] + ... + c[n] - a[n] = 0
a[1] + a[2] + ... + a[n] = c[1] + c[2] + ... + c[n] = 0
*/

浙公网安备 33010602011771号