[差分] P4552 [Poetize6] IncDec Sequence 题解

据说是一个相当经典的差分问题呢。

问题链接: P4552

看第一问。

首先是一个区间操作的转化。我们发现题目中的区间加减其实就是差分数组的单点加减。

也就是说他这个题目条件就转换成了,你单次操作可以在差分数组选两个位置一个加1一个减1,或者选单一个位置加1或减1,问你几次操作能让差分数组全是0。

是不是比较简单的贪心就能看出来了,首先把能同时消掉的给消了,剩下的就只能一个一个改。

我们假设差分数组中正数的和是 \(sum1\) , 负数和的相反数是 \(sum2\)。那你能一起消掉的就是 \(\min(sum1 , sum2)\)只能单独消掉的就是 \(\max(sum1 , sum2) - \min(sum1 , sum2)\)

加一起答案就是 \(\max(sum1 , sum2)\)

第二问。

事先声明,默认的前提是最终数组的元素都等于数组第一个元素。

考虑一下为啥会在步数最少的前提下,有不同的情况。

其实就是因为你修改一个差分数组的元素,实际可以有两种操作。

比如下面这个数组。

\[1 , 1 , 2 , 3 , 4 \]

差分数组是

\[0 , 1 , 1 , 1 \]

你要把第二个差分数组元素改成 0 , 那么你对实际数组的操作其实有两种做法。

一种是这么改

\[1 ,1 , 1 , 2 , 3 \]

一种是这么改

\[2 , 2 , 2 , 3 , 4 \]

也就是说,你每有一个单独的操作,你都可以选择该前面还是改后面,也就是是否改动第一个元素。这样,就让最终答案多了一种情况。

上文提到过单独消掉的操作个数是 \(\max(sum1 , sum2) - \min(sum1 , sum2)\) 个,因此第二问答案就是 \(\max(sum1 , sum2) - \min(sum1 , sum2) + 1\) , 加的那个 1 就是啥改动也不做。

#include <bits/stdc++.h>
#define int long long
constexpr int N = 1e5 + 5;
using namespace std;
int n , sum1 , sum2 , a[N] , d[N];
signed main() {
	cin >> n;
	for(register int i = 1; i <= n; ++i) {
		cin >> a[i];
	}
	for(register int i = 1; i < n; ++i) {
		d[i] = a[i + 1] - a[i];
		if(d[i] < 0) sum1 += -d[i];
		else sum2 += d[i]; 
	}
	cout << max(sum1 , sum2) << '\n' << max(sum1 , sum2) - min(sum1 , sum2) + 1; 
	return 0;
}
posted @ 2025-06-15 22:41  「癔症」  阅读(15)  评论(0)    收藏  举报