LCP 24. 数字游戏

令数组满足 n u m s [ i ] + 1 = n u m s [ i + 1 ] nums[i]+1=nums[i+1] nums[i]+1=nums[i+1],经典问题了,直接做不好做,因为每个数字被位置信息制约了,一般来说这样制约可能就会想去dp或爆搜。但也可以通过转化一下数组变为好做的形式。
n u m s [ i ] + 1 = n u m s [ i + 1 ] → n u m s [ i ] − i = n u m s [ i + 1 ] − ( i + 1 ) nums[i]+1=nums[i+1] \rightarrow nums[i]-i=nums[i+1]-(i+1) nums[i]+1=nums[i+1]nums[i]i=nums[i+1](i+1)
因此,题目就转化为最少的步骤满足 ∀ i , n u m s [ i ] − i = k \forall i,nums[i]-i=k i,nums[i]i=k
n u m s n e w [ i ] = n u m s [ i ] − i nums_{new}[i] = nums[i]-i numsnew[i]=nums[i]i,这样的话只要保证所有 n u m s n e w [ i ] nums_{new}[i] numsnew[i]相等就可以了。

然后问题就转换成n个数字通过加1减1最小需要多少步才能使其全部相等。

  • 先证明最终相等的数必然是数组中的一个元素

假设a是一个坐标,令 n u m s [ a ] < = x < n u m s [ a + 1 ] nums[a]<=x<nums[a+1] nums[a]<=x<nums[a+1],则使所有数都等于x的代价为
a ∗ x − ∑ i = 1 a n u m s [ i ] + ∑ i = a + 1 n n u m s [ i ] − ( n − a ) ∗ x = ( 2 a − n ) x − ∑ i = 1 a n u m s [ i ] + ∑ i = a + 1 n n u m s [ i ] a*x-\sum_{i=1}^anums[i]+\sum_{i=a+1}^nnums[i]-(n-a)*x=(2a-n)x-\sum_{i=1}^anums[i]+\sum_{i=a+1}^nnums[i] axi=1anums[i]+i=a+1nnums[i](na)x=(2an)xi=1anums[i]+i=a+1nnums[i]
f ( x ) = ∑ i = 1 x n u m s [ i ] f(x)=\sum^x_{i=1}nums[i] f(x)=i=1xnums[i]
则代价为 ( 2 a − n ) x + f ( n ) − 2 f ( a ) (2a-n)x+f(n)-2f(a) (2an)x+f(n)2f(a),由于 f ( n ) f(n) f(n)是已知的,令 g ( x ) = ( 2 a − n ) x − 2 f ( a ) g(x)=(2a-n)x-2f(a) g(x)=(2an)x2f(a)
目的就是使 g ( n ) g(n) g(n)尽可能小,此时令 x = n u m s [ a ] x = nums[a] x=nums[a]有最小值,因此最终值k一定是其中的一个数值。

  • 然后证明中位数最好

d ( a ) = ( 2 a − n ) n u m s [ a ] − 2 f ( a ) d(a) = (2a-n)nums[a]-2f(a) d(a)=(2an)nums[a]2f(a)

d ( a + 1 ) − d ( a ) = ( 2 a + 2 − n ) n u m s [ a + 1 ] − 2 f ( a + 1 ) − ( 2 a − n ) n u m s [ a ] + 2 f ( a ) = ( 2 a + 2 − n ) n u m s [ a + 1 ] − 2 n u m [ a + 1 ] − ( 2 a − n ) n u m s [ a ] = ( 2 a − n ) n u m s [ a + 1 ] − ( 2 a − n ) n u m s [ a ] = ( 2 a − n ) ( n u m s [ a + 1 ] − n u m s [ a ] ) d(a+1)-d(a) = (2a+2-n)nums[a+1]-2f(a+1)-(2a-n)nums[a]+2f(a) \\ = (2a+2-n)nums[a+1]-2num[a+1]-(2a-n)nums[a] \\ = (2a-n)nums[a+1]-(2a-n)nums[a] \\ =(2a-n)(nums[a+1]-nums[a]) d(a+1)d(a)=(2a+2n)nums[a+1]2f(a+1)(2an)nums[a]+2f(a)=(2a+2n)nums[a+1]2num[a+1](2an)nums[a]=(2an)nums[a+1](2an)nums[a]=(2an)(nums[a+1]nums[a])
因此 ∇ d = ( 2 a − n ) ( n u m s [ a + 1 ] − n u m s [ a ] ) \nabla d= (2a-n)(nums[a+1]-nums[a]) d=(2an)(nums[a+1]nums[a]),由于 n u m s [ a + 1 ] − n u m s [ a ] > = 0 nums[a+1]-nums[a]>=0 nums[a+1]nums[a]>=0
显然有
{ ∇ d < = 0 , 2 a − n < 0 ∇ d > = 0 , 2 a − n > 0 \left\{ \begin{aligned} \nabla d<=0 & & ,2a-n<0 \\ \nabla d>=0 & & ,2a-n>0 \end{aligned} \right. {d<=0d>=0,2an<0,2an>0
即当 a < n / 2 a<n/2 a<n/2时, d ( a ) d(a) d(a)递减,而 a > n / 2 a>n/2 a>n/2时, d ( a ) d(a) d(a)递增。
因此得出结论,当a为中位数时,d(x)有最小值。

找所有[0,i]的中位数就可以了,方法有很多,优先队列,线段树啥的都行。代码有空再补

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值