P4552 IncDec Sequence|差分经典贪心题完整博客题解
一、题目题意

题目规则
给定长度为 $n$ 的序列 $a_1,a_2,\dots,a_n$,支持两种操作:
- 选定区间 $[l,r]$,区间内所有数字 $+1$;
- 选定区间 $[l,r]$,区间内所有数字 $-1$。
要求输出两个答案:
- 将整个数列所有数字变为相同值的最少操作次数;
- 在保证操作次数最少的前提下,最终相同数字一共有多少种可能。
样例解读
输入:
4
1
1
2
2
原数组 $a=[1,1,2,2]$
差分数组 $b=[1,0,1,0]$
统计正数差分总和 $p=1$,负数差分绝对值总和 $q=0$
最少操作次数 $\max(1,0)=1$;可行答案种类 $|1-0|+1=2$,对应输出 1 和 2。

二、核心算法:差分 + 贪心
1. 差分定义
定义差分数组 $b$,其中:
$$b_1 = a_1,\quad b_i = a_i - a_{i-1}\quad (i\ge2)$$
原数组区间操作等价于差分单点修改:
- 区间 $[l,r]$ 全部 $+1$:$b[l] += 1,\ b[r+1] -=1$(若 $r+1\le n$);
- 区间 $[l,r]$ 全部 $-1$:$b[l] -= 1,\ b[r+1] +=1$(若 $r+1\le n$)。
2. 目标转化
题目要求所有数字相等,等价于:原数组差分 $b_2,b_3,\dots,b_n$ 全部变为 $0$。
因为若 $b_2=b_3=\dots=b_n=0$,则 $a_1=a_2=\dots=a_n$。
$b_1$ 可以是任意整数,对应最终统一后的数值。
3. 最少操作次数推导
设:
- $p$:$b_2\sim b_n$ 中所有正数的总和;
- $q$:$b_2\sim b_n$ 中所有负数的绝对值总和。
- 正数差分需要用区间 $+1$ 操作抵消,总消耗 $p$ 次;
- 负数差分需要用区间 $-1$ 操作抵消,总消耗 $q$ 次;
- 正负操作可以互相复用一部分区间,最少总操作次数为 $\max(p,q)$。
4. 可行最终值的数量推导
$b_1$ 可以自由变化,变化范围长度为 $|p-q|$,因此总可行种类:
$$|p - q| + 1$$

三、完整AC代码
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 100010;
int a[N], b[N];
int main() {
int n;
cin >> n;
for(int i=1; i<=n; i++) cin >> a[i];
// 构建差分数组
for(int i=1; i<=n; i++) b[i] = a[i]-a[i-1];
LL p = 0, q = 0;
// 统计b[2]~b[n]正负总和
for(int i=2; i<=n; i++){
if(b[i]>0) p+=b[i];
else q+=abs(b[i]);
}
// 最少操作次数、可行数值种类
cout<<max(p,q)<<'\n'<<abs(p-q)+1;
return 0;
}
四、分步完整解题流程
步骤1:读入原数组
读取序列长度 $n$,循环存入数组 $a[1\sim n]$。
步骤2:构建差分数组
循环计算 $b[i] = a[i]-a[i-1]$,得到完整差分序列。
我们只需要处理下标 $2\sim n$ 的差分,目标是将它们全部归零。
步骤3:统计正负差分总和
遍历 $i=2$ 到 $n$:
- 若 $b[i]>0$,累加到正数总和 $p$;
- 若 $b[i]<0$,累加其绝对值到 $q$。
步骤4:计算并输出答案
- 最少操作次数:$\max(p,q)$;
- 最终相同数字的方案数:$|p-q| + 1$;
分行打印两个结果。
五、代码分段详解
1. 常量与变量定义
typedef long long LL;
const int N = 100010;
int a[N], b[N];
- $N=100010$:适配题目数据范围 $n\le 10^5$;
a[]:存储原始输入数列;b[]:差分数组;LL p,q:防止累加数值过大,使用长整型存储正负差分总和。
2. 读入数组 + 差分构造
for(int i=1; i<=n; i++) cin >> a[i];
for(int i=1; i<=n; i++) b[i] = a[i]-a[i-1];
标准差分构造公式,$a[0]$ 默认初始为0,不影响计算。
3. 统计正负差分总和
LL p = 0, q = 0;
for(int i=2; i<=n; i++){
if(b[i]>0) p+=b[i];
else q+=abs(b[i]);
}
只遍历 $b_2$ 到 $b_n$,这部分差分需要全部清零;$p$ 记录所有正数差分总和,$q$ 记录负数差分绝对值总和。
4. 输出两组答案
cout<<max(p,q)<<'\n'<<abs(p-q)+1;
- $\max(p,q)$:最少区间操作次数;
- $|p-q|+1$:满足最少操作前提下,最终相同数字的总种类。
六、题型总结
- 模型定位:差分区间操作经典贪心模板题,是差分入门必做题;
- 核心转化:区间修改 → 差分单点修改,数列全相等 → 后缀差分全部为0;
- 两个结论记忆点:
- 最少操作次数 = 正差分总和、负差分绝对值总和二者最大值;
- 最终统一数值方案数 = 两个总和差值的绝对值 $+1$;
- 拓展延伸:差分可快速解决大量区间增减、最小操作次数类问题。
浙公网安备 33010602011771号