思路很神,经验很足的一道题。
题目
首先记
b
i
=
a
i
−
i
b_i=a_i-i
bi=ai−i,然后把严格递增变成非严格递增。
用一个优先队列维护
i
i
i 以前的所有值,对于所有当前值大于
a
i
a_i
ai 的值改为
a
i
a_i
ai 然后贡献
v
a
l
−
a
i
val-a_i
val−ai 的操作次数。
这个思路看起来就很不对,但是是正确的。
首先,对于一对不符合非降的
(
x
,
y
)
(x,y)
(x,y)
x
<
y
,
a
x
>
a
y
x<y,a_x>a_y
x<y,ax>ay 肯定是将
a
x
a_x
ax 尽量减少,
a
y
a_y
ay 尽量增加才可以使答案更优。如果不考虑
x
x
x 之前的
z
z
z 满足
a
z
a_z
az 的最终值大于
a
y
a_y
ay,那么就将
a
x
a_x
ax 改为
a
z
a_z
az。如果考虑
z
z
z 的话,将
a
x
a_x
ax 和
a
y
a_y
ay 改为
a
z
a_z
az 的最终值还是贡献
a
x
−
a
y
a_x-a_y
ax−ay,即
a
z
a_z
az 的最终值不影响
(
x
,
y
)
(x,y)
(x,y) 计算贡献。
要求输出方案的经验
其实感觉这种做法比前面的更好想到。
严格递增还是用上面的方法转换成非严格递增。
首先发现对于两种特殊的序列(严格递增和严格递减的序列)最终都是将所有数改为这个序列的中位数。所以将原序列分成若干个单调递减的序列,对于前一个段的中位数大于后一个段的中位数,需要合并,并改成合并后的中位数。
用可并堆维护中位数,也就是先加入一个段中的所有数,然后删除一半的数,此时最大值就是中位数。唯一担心的是如果合并前已经删除了合并后的中位数,那么就不对了。可以注意到,如果前一个段大于的中位数后一个段的,那么合并后的中位数在前一个段时则 咕咕咕