CF1852C

题意

给定 \(K\)

给出长为 \(N\) 的序列 \(a\)\(0\le a_i< K\)

你可以先进行以下预操作若干次:\(a_i \leftarrow a_i+K\)

定义 \(\text{rock}(l,r)\) 操作为 \(\forall i\in[l,r],a_i\leftarrow a_i-1\)

对你进行操作后的数列,求最小的 \(\text{rock}\) 操作次数,使 \(\forall i,a_i=0\)

sample: K=3
1 2 0 1 0 2 1
预操作后为
1 2 3 4 3 2 1
答案为 \(4\)

题解

若不能进行预操作,则为经典问题。

定义 \(da\)\(a\) 的差分序列,得 \(ans=\sum_{i=1}^N \max(da_i,0)\)

直接考虑差分序列。增量考虑:

记当前数为 \(x\),上一个是 \(y\)

\(x\le y\),则此处贡献要么为 \(0\),要么为 \(x+K-y\)

\(x>y\),则此处贡献为 \(x-y\)

考虑当前的所有贡献,直接压进堆里,当 \(x>y\) 时取出最小的即可。

//pq 为 priority_queue 实现小根堆
scanf("%lld%lld",&N,&K);
while(N--){
    ll x;
    scanf("%lld",&x);
    //if(x==K) x=0;
    if(x>be){
        pq.push(x-be);
        ans+=pq.top();
        pq.pop();
    }else{
        pq.push(K+x-be);
    }
    be=x;
}
printf("%lld\n",ans);
posted on 2023-07-24 09:58  Zaunese  阅读(37)  评论(0编辑  收藏  举报