题目:
http://cogs.pro/cogs/problem/problem.php?pid=1883
为了提高自己的实力,gx想要制定一个合理的刷题计划。这里我们用实数来表示题目的难度,并且把刷题计划中由题目难度组成的序列称为刷题序列。gx刷题最喜欢循序渐进的方式,最理想的情况莫过于刷题序列是个等差数列了。但是这很难做到,于是我们定义一个刷题序列a的偏离值
,其中L是给定的一个常数。
现在gx的老师已经布置给了他n道必做题,同时他还有空余时间从OJ上找m道题目来刷。他不希望改变这n道必做题的相对顺序,但是选做题的难度以及在数列中的位置都是任意的(OJ上的题目太多了,随你怎么挑)。
gx希望你帮他设计一个刷题序列,使得该序列的偏离值最小。
现在gx的老师已经布置给了他n道必做题,同时他还有空余时间从OJ上找m道题目来刷。他不希望改变这n道必做题的相对顺序,但是选做题的难度以及在数列中的位置都是任意的(OJ上的题目太多了,随你怎么挑)。
gx希望你帮他设计一个刷题序列,使得该序列的偏离值最小。
分析:
其实这道题和“骑行川藏”很像,但它是11年的,当时后者还没出来……
首先明确一下题意。假设我们要在a[i]和a[i+1]之间放一些题,那必然是这样的:
为什么呢?
假设某一段的长度为c,我们试图在中间加一道题,把它分成两段a,b,自然a+b=c。
其代价为:
所以相邻两段相等时代价最小。用调整法可以证明,在a[i]~a[i+1]之间放题一定是均分才能使代价最小。
(当然你也可以用柯西不等式证明)
所以题目就变成了:将这N-1段分别进行均分,使得新插入的点数之和<=M,并且代价最小。
(至于M道题中没有用上的部分,可以接在最后一道后面成为等差数列,其代价为零)
像“骑行川藏”一样,我们来考虑每一段的代价。
假设我们把长度d的一段(注意d可能为负)均分成了k段,代价是:
所以可以设想出一个这样的算法:一开始每一段都分成了1份。然后对于M次操作,每次选取增量最小的(也就是改进值最大的)一段,在其中多加一个点。
但是M非常大,怎么办?
在结束时,增量可能是这样的:
算法就很好办了:二分结束时的最小增量,然后计算每一段被分成了多少份。好像没什么奇怪的细节……
代码: