AtCoder Regular Contest 129 D -1+2-1

洛谷传送门

AtCoder 传送门

挺有趣的题。自己推出来感觉挺有意思的。

首先显然若 \(\sum\limits_{i=0}^{n-1} a_i \ne 0\) 就无解。

\(b_i\)\(i\) 的操作次数。可得:

\[-b_{i-1} + 2b_i - b_{i+1} = a_i \]

整理得:

\[b_i = \frac{b_{i-1} + b_{i+1} - a_i}{2} \]

发现因为有 \(i - 1\)\(i + 1\) 不好处理。考虑一个通用套路就是设 \(b_i = x_i b_{i-1} + c_i\),得:

\[b_i = \frac{b_{i-1} + x_{i+1} b_{i} + c_{i+1} - a_i}{2} \]

整理得:

\[b_i = \frac{1}{2 - x_{i+1}} b_{i-1} + \frac{1}{2 - x_{i+1}} (c_{i+1} + a_i) \]

那么 \(x_i = \frac{1}{2 - x_{i+1}}\),解得 \(\forall i \in [1, n], x_i = 1\)。那么:

\[b_i = b_{i-1} + c_{i+1} - a_i \]

得到:

\[c_i = c_{i+1} - a_i \]

发现 \(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
*/
posted @ 2023-05-12 22:17  zltzlt  阅读(27)  评论(0)    收藏  举报