【杂题题解】ABC467 E - Adjacent Sums (hard)
洛谷传送门:https://www.luogu.com.cn/problem/AT_abc467_e
AT 传送门:https://atcoder.jp/contests/abc467/tasks/abc467_e
这道题的本质是:我们只能把每个数增加,所以对于最终余数 \(r_i\),最小增加次数为
其中取模结果在 \([0, M-1]\)。
而条件只和余数有关:
一旦确定了第一个数的余数 \(r_1 = t\),后面所有 \(r_i\) 就唯一确定了:
其中 \(u_1 = 0\),并且递推:
也就是说:
- 若 \(i\) 为奇数,\(r_i \equiv u_i + t \pmod M\)
- 若 \(i\) 为偶数,\(r_i \equiv u_i - t \pmod M\)
记
那么位置 \(i\) 的代价就是
其中
所以总代价为
我们需要在 \(t\in [0, M-1]\) 中最小化 \(F(t)\)。
把奇偶位置分开:
-
奇数位置 \(i\):
\[(w_i + t) \bmod M = \begin{cases} w_i + t, & w_i + t < M \\ w_i + t - M, & w_i + t \ge M \end{cases} \]等价于:先加 \(t\),但如果 \(w_i \ge M - t\),就再减一个 \(M\)。
-
偶数位置 \(i\):
\[(w_i - t) \bmod M = \begin{cases} w_i - t, & w_i \ge t \\ w_i - t + M, & w_i < t \end{cases} \]等价于:先减 \(t\),但如果 \(w_i < t\),就再加一个 \(M\)。
因此:
注意:
要么是 \(0\),要么是 \(1\)。
把 \(F(t)\) 看成关于 \(t\) 的函数,随着 \(t\) 增加:
- 奇数项对斜率的贡献是 \(+1\);
- 偶数项对斜率的贡献是 \(-1\)。
所以区间内斜率恒为:
也就是说,在两个"拐点"之间,\(F(t)\) 不会下降,只可能不变或上升,我们需要枚举的值就在拐点上。
拐点发生在某个 \(w_i + s_i t\) 刚好等于 \(0\) 或 \(M\) 的地方,也就是某个位置的代价刚好为 \(0\) 的情况:
-
若 i 为奇数,令 \(w_i + t \equiv 0 \pmod M\),解得
\[t \equiv A_i - u_i \pmod M \] -
若 i 为偶数,令 \(w_i - t \equiv 0 \pmod M\),解得
\[t \equiv u_i - A_i \pmod M \]
所以只需要枚举这 \(N\) 个候选 \(t\) 即可。
预处理:
- 把所有奇数位置的 \(w_i\) 放入数组 \(p1\),排序;
- 把所有偶数位置的 \(w_i\) 放入数组 \(p0\),排序;
- 计算 \(sum = \sum w_i\)。
对于给定的 \(t\):
-
奇数部分需要减去 \(M\) 的个数:
id = lower_bound(p1, M - t) - p1; cnt = cnt1 - id + 1; res -= cnt * M; -
偶数部分需要加上 \(M\) 的个数:
id = lower_bound(p0, t) - p0 - 1; // id 就是 w_i < t 的个数 res += id * M;
再加上基础值:
res = sum + (n % 2) * t;
枚举所有候选 \(t\),取最小值即可。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5 + 10;
const ll inf = 0x3f3f3f3f3f3f3f3f;
ll n, M, a[N], b[N];
ll u[N], p1[N], p0[N];
ll cnt1, cnt0;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> M;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i < n; i++)
cin >> b[i];
u[1] = 0;
for (int i = 2; i <= n; i++)
u[i] = (b[i - 1] - u[i - 1] + M) % M;
ll alsum = 0ll;
for (int i = 1; i <= n; i++) {
if (i & 1) {
p1[++cnt1] = (u[i] - a[i] + M) % M;
alsum += p1[cnt1];
} else {
p0[++cnt0] = (u[i] - a[i] + M) % M;
alsum += p0[cnt0];
}
}
sort(p1 + 1, p1 + cnt1 + 1);
sort(p0 + 1, p0 + cnt0 + 1);
ll ans = inf;
for (int i = 1; i <= n; i++) {
ll t = 0;
if (i & 1) t = (a[i] - u[i] + M) % M;
else t = (u[i] - a[i] + M) % M;
ll res = alsum + (n % 2) * t;
int id = lower_bound(p1 + 1, p1 + cnt1 + 1, M - t) - p1;
res -= (cnt1 - id + 1LL) * M;
id = lower_bound(p0 + 1, p0 + cnt0 + 1, t) - p0 - 1;
res += (id + 0LL) * M;
ans = min(ans, res);
}
cout << ans << "\n";
return 0;
}

浙公网安备 33010602011771号