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;
}
posted @ 2023-07-25 00:30  SFlyer  阅读(12)  评论(0编辑  收藏  举报