P11119 [ROI 2024 Day 2] 保持连接
P11119 [ROI 2024 Day 2] 保持连接
更好的阅读体验
设
如果没有
加上
设
实现时可以开两棵树状树组维护个数和贡献,代码非常精简。
#include <bits/stdc++.h>
#define int long long
#define lb(x) (x & (-x))
using namespace std;
bool START;
const int N = 1e6 + 5;
int n, X, a[N], L[N], R[N];
int f[N], g[N], S, ans;
struct bit {
int c[N];
void add(int x, int k) {for (; x <= n; x += lb(x)) c[x] += k;}
int ask(int x) {int s = 0; for (; x; x -= lb(x)) s += c[x]; return s;}
} t1, t2;
bool END;
signed main() {
cin >> n >> X; for (int i = 1; i <= n; ++i) L[i] = i, R[i] = i;
for (int i = 1; i <= n; ++i) {
cin >> a[i]; int r = min(n, i + a[i]), l = max(1ll, i - a[i]);
L[r] = min(L[r], l), R[l] = max(R[l], r);
}
for (int i = n - 1; i; --i) L[i] = min(L[i], L[i + 1]);
for (int i = 2; i <= n; ++i) R[i] = max(R[i], R[i - 1]);
for (int i = n - 1; i; --i) g[i] = n - R[i] + g[R[i] + 1];
for (int i = 1; i <= n; ++i) f[i]++, f[R[i] + 1] += f[i];
for (int i = 1; i <= n; ++i) S += g[i];
ans = S;
for (int i = 1; i <= n; ++i) t1.add(i, g[i]), t2.add(i, 1);
for (int i = 1; i <= n; ++i) {
int p = (i + X <= n ? L[i + X] : n + 1);
int l = max(1ll, i - X), r = min(n, i + X);
if (l > 1) {
int t = l - 1;
if (R[t] + 1 <= n) t1.add(R[t] + 1, f[t] * g[R[t] + 1]), t2.add(R[t] + 1, f[t]);
}
if (X <= a[i]) continue;
if (p <= l) continue;
int s = S - (t1.ask(p - 1) - t1.ask(l - 1)) + (t2.ask(p - 1) - t2.ask(l - 1)) * (n - r + g[r + 1]);
ans = min(ans, s);
}
cout << ans << endl;
return 0;
}