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);