CF 1853 E
首先,所有的都\(\mod k\)。\(i+1\) 的最优一定从 \(i\) 的最优转化而来。也就是这题让我们做出最优的 \(extend\)。
可以算一下样例。1 2 3 1 3 2 1
的答案依次为 1 2 3 3 4 4 4
。可以得到一个 observation:
- observation:当在走下坡路的时候,答案不变。
- why:可以理解为当上坡的全变成 \(k\) 了,下坡的一定有一种可以。
尝试 \(i\) 最优了,延申到 \(i+1\) 最优。
- 若 \(a_{i+1}\le a_i\),加上前面最少的需要次数和 \(a_i-a_{i-1}\) 的 \(\min\)。(最少的需要次数是若 \(i\) 带着 \(i+1\),\(i\) ok了,\(i+1\) 还要?)需要次数 push 一个 \(a_i-a_{i-1}\)。
- 反之,不需要加答案。需要次数 push 一个 \(k-(a_{i-1}-a_i)\)。
#include <bits/stdc++.h>
using namespace std;
#define de(x) cout<<#x<<"="<<x<<endl
using ll = long long;
const int N = 2e5+5;
int n,k;
int a[N];
void solve(){
cin>>n>>k;
for (int i=1; i<=n; i++){
cin>>a[i];
a[i]%=k;
// cout<<a[i]<<" ";
}
// cout<<endl;
a[0]=0;
multiset<int> st;
ll ans=0;
for (int i=1; i<=n; i++){
if (a[i]>=a[i-1]){
st.insert(a[i]-a[i-1]);
ll mn=*st.begin();
st.erase(st.begin());
ans+=mn;
// cout<<mn<<endl;
}
else{
st.insert(k-(a[i-1]-a[i]));
}
}
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while (t--){
solve();
}
return 0;
}