CF1736C2 Good Subarrays (Hard Version)
对于 C1,有一种做法是固定右端点,设
我们在这个基础上解决 C2。
假设修改是
如果我们能找到这样一个最小的
所以可以处理出这么一个
假设找出了这么一个
还剩下
接下来问题是,
对于找
首先由
于是我们把询问 upper_bound 即可。
对于计算
伪代码如下:
sort ALL by (x - p)
for (p, x, op) in ALL
if op is ASK
q = upper_bound(p) in S
update(op)
else
q = upper_bound(p) in S
insert p into S
update(g[p])
// Problem: C2. Good Subarrays (Hard Version)
// URL: https://codeforces.com/contest/1736/problem/C2
// Group: Codeforces - Codeforces Round #825 (Div. 2)
// Time: 2022-10-10 22:36
// Author: lingfunny
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int mxn = 2e5 + 10;
int q, n, a[mxn], m, f[mxn];
LL S[mxn], res[mxn], pre[mxn], g[mxn];
struct ASK {
int op, x, p;
} ask[mxn * 2];
signed main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", a + i);
f[i] = min(f[i - 1] + 1, a[i]);
S[i] = S[i - 1] + i;
pre[i] = pre[i - 1] + f[i];
ask[++m] = { 0, a[i], i };
}
scanf("%d", &q);
for (int i = 1; i <= q; ++i) {
int p, x;
scanf("%d%d", &p, &x);
x = min(x, f[p - 1] + 1);
ask[++m] = { i, x, p };
}
sort(ask + 1, ask + m + 1, [&](const ASK &a, const ASK &b) {
int wa = a.x - a.p, wb = b.x - b.p;
if (wa == wb) return a.op > b.op;
else return wa < wb;
});
set<int> ava = { n + 1 };
for (int i = 1; i <= m; ++i) {
auto [op, x, p] = ask[i];
if (!op) {
q = *ava.upper_bound(p);
g[p] = g[q] + S[q - p] + (LL)(q - p) * (a[p] - 1);
ava.insert(p);
} else {
q = *ava.upper_bound(p);
res[op] = pre[p - 1] + S[q - p] + (LL)(q - p) * (x - 1) + g[q];
}
}
for (int i = 1; i <= m - n; ++i) printf("%lld\n", res[i]);
return 0;
}