CF1852C Ina of the Mountain 题解
设 $i$ 章鱼最终被打了 $c_i|c_i\equiv a_i\pmod k$,则答案为 $\sum\limits_{i=1}^n\max(c_i-c_{i-1},0)$。
有结论:$\forall i,-k<c_i-c_{i-1}<k$。
(证明:若 $c_i-c_{i-1}\ge k$,那将 $c_i\gets c_i-k$ 满足结论,此时 $c_i-c_{i-1}$ 减少 $k$,而 $c_{i+1}-c_i$ 至多增加 $k$,不会变劣)
于是每个 $c_i-c_{i-1}$ 只会有两种取值 $A_i<0,B_i>0$,考虑对每一位选择 $A_i$ 或 $B_i$,
同时需要保证每段前缀选择的数之和(即为 $c_i$)非负。
从前往后依次选择,能选 $A_i$ 就选 $A_i$(贡献为 $0$),否则考虑:
- 选 $B_i$(贡献为 $B_i$),
- 把之前某个 $A_j$ 改成 $B_j$(贡献为 $B_j$),然后选 $A_i$。
堆维护之。
#include <queue>
#include <cstdio>
#define int long long
using namespace std;
int T, n, k, s, z, a[200050];
signed main()
{
scanf("%lld", &T);
while (T--)
{
s = z = 0;
priority_queue<int, vector<int>, greater<int>> q;
scanf("%lld%lld", &n, &k);
for (int i = 1, A, B, C; i <= n; ++i)
{
scanf("%lld", a + i);
if (!(B = (a[i] - a[i - 1] + k) % k))
continue;
A = B - k;
if (s + A >= 0)
s += A, q.push(B);
else
{
C = q.empty() ? 1e18 : q.top();
if (C < B)
s += A + k, z += C, q.pop(), q.push(B);
else
s += B, z += B;
}
}
printf("%lld\n", z);
}
return 0;
}