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;
}
posted @ 2023-08-14 15:15  5k_sync_closer  阅读(1)  评论(0编辑  收藏  举报  来源