题解:AT_arc182_d [ARC182D] Increment Decrement Again

posted on 2025-02-20 11:18:38 | under | source

这个取模很烦,考虑转化:不取模,但是要求 \(0<|a_i-a_{i+1}|< m\)

注意到怎么操作 \(a_i,a_{i+1}\) 的大小关系不会变,否则必然出现相等情况。大胆猜测对于一个合法的终止态 \(t\)(合法定义为大小关系不变且满足限制),一定有解,且步数最小为 \(\sum|a_i-t_i|\)

证明如下:首先显然是下界。然后归纳证明,先构造 \(i\in [2,n]\) 的解,然后分讨一下 \(a_1,a_2\) 大小关系,不妨设 \(a_1<a_2\),假如 \(a_1\le t_1\),那么直接把 \(a_1\) 加到 \(t_1\) 即可。否则 \(a_1>t_1\),可以在 \(a_2\) 减到 \(a_1+1\) 时,让 \(a_1\) 跟着 \(a_2\) 一起减,最后再移到 \(t_1\) 即可。

不过上述构造在 \(m=2\) 时不成立,需要特判一下。

那么问题就简单了。注意到一旦确定 \(t_1\),就能利用大小关系唯一确定整个 \(t\) 序列。不妨先构造任意一组合法终止态 \(t^\prime\),答案即为 \(\min \sum|a_i-(t^{\prime}_i+km)|\)。这不初一数学题吗,只需中位数左右相邻两组解即可。

\(O(n\log n)\),可以做到 \(O(n)\)

代码

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int N = 2e5 + 5;
int n, m, a[N], b[N], c[N], ans; 

inline int myz(int x) {return x < 0 ? -x : x;}
inline int Ceil(int a, int b){
	if(a >= 0) return a / b * b;
	if(a % b == 0) return a;
	return (a / b - 1) * b;
}
inline int sum(int x){
	int res = 0;
	for(int i = 1; i <= n; ++i) res += myz(c[i] - x); 
	return res;   
}
signed main(){
	cin >> n >> m;
	for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
	for(int i = 1; i <= n; ++i) scanf("%lld", &b[i]);
	if(m == 2){
		for(int i = 1; i <= n; ++i)
			if(a[i] ^ b[i]){
				puts("-1");
				return 0;
			} 
		puts("0");
		return 0;
	}
	c[1] = b[1];
	for(int i = 1; i < n; ++i)
		if(a[i] < a[i + 1]){
			if(b[i] < b[i + 1]) c[i + 1] = c[i] + b[i + 1] - b[i];
			else c[i + 1] = c[i] + b[i + 1] + m - b[i];
		}
		else{
			if(b[i] > b[i + 1]) c[i + 1] = c[i] - (b[i] - b[i + 1]);
			else c[i + 1] = c[i] - (b[i] + m - b[i + 1]);
		}
	for(int i = 1; i <= n; ++i) c[i] = a[i] - c[i];
	sort(c + 1, c + 1 + n);
	cout << min(sum(Ceil(c[n / 2 + 1], m)), sum(Ceil(c[n / 2 + 1], m) + m));
	return 0;
}
posted @ 2026-01-15 08:14  Zwi  阅读(3)  评论(0)    收藏  举报