正确性证明
1. 最少操作次数为 max(x, y)
- 差分序列的性质:对原序列
a
的区间[l, r]
进行加k
的操作,等价于对差分序列b
中的b[l]
加k
,b[r + 1]
减k
(如果r + 1 <= n
)。要将原序列a
变成所有元素都相等的序列,等价于将差分序列b
除b[1]
外的所有元素都变为 0。 - 操作策略:可以同时对正的差分和负的差分进行操作。每次操作可以选择一个正的差分和一个负的差分,将它们同时向 0 靠近。例如,有一个正的差分
b[i]
和一个负的差分b[j]
,可以选择一个合适的k
,使得b[i]
减去k
,b[j]
加上k
,这样就可以同时减少两个差分的绝对值。 - 操作次数分析:由于正的差分总和为
x
,负的差分总和为y
,在尽量配对操作的情况下,当较小的一方(min(x, y)
)变为 0 时,剩下的操作次数就是较大的一方(max(x, y)
)。因此,最少操作次数为max(x, y)
。
2. 最终序列可能的不同取值数量为 abs(x - y) + 1
- 最终序列的取值与差分的关系:最终序列的取值取决于对
b[1]
的操作。在将差分序列b
除b[1]
外的所有元素都变为 0 的过程中,对b[1]
的影响是由剩余未配对的操作决定的。 - 剩余操作的影响:当
x > y
时,最后剩下x - y
次正的操作,这些操作可以作用在b[1]
上,使得b[1]
增加0
到x - y
之间的任意整数;当x < y
时,最后剩下y - x
次负的操作,这些操作可以作用在b[1]
上,使得b[1]
减少0
到y - x
之间的任意整数。因此,最终序列可能的不同取值数量为abs(x - y) + 1
。
核心代码:
for (int i = 2; i <= n; i++) {
b[i] = a[i] - a[i - 1];
if (b[i] > 0) x += b[i];
else y -= b[i];
}
最后只需要输出:
cout << max(x, y) << "\n" << abs(x - y) +1;