AGC004B 线性做法

$\text{Description}$

有 $n$ 个所罗门,你需要执行以下两个操作:

  • 花费 $x$,将你拥有的所罗门的编号都循环地加一。
  • 花费 $a_i$,拥有第 $i$ 个所罗门

来获得所有所罗门,并最小化花费。

原题:$2\le n\le 2000$。

加强:$2\le n\le 10^6$。

$\text{Solution}$

首先有特别显然的结论。

每个所罗门一定都是从另一个所罗门变过来的。

设 $p(x)$ 表示第 $x$ 个所罗门是从第 $p(x)$ 个所罗门变过来的,$d(i)=p(i)-i+[p(i)<i]n$,换句话说,它是环上 $i$ 到 $p(i)$ 的顺时针距离。

那么对于一个 $p$,它的花费是:

构造很简单,将所有元素按照 $d$ 降序排列,然后依次执行对应的抓捕操作,接着执行对应次数的魔法操作即可。

这时就有个简单的做法,枚举 $\max_i d(i)$,那么 $x\max_i d(i)$ 就是定值,那我们知道对于 $p(i)$ 我们只需选择在范围内且 $a$ 最小的下标。

在原题的数据范围内,直接预处理所有区间的最小值就可以做到 $O(n^2)$。

记 $D=\max_i d(i),S(D)=\sum_{i}a_{p(i)}$。

转换一下思路,设 $c(i)$ 表示在某个 $D$ 下,$i$ 作为 $p(j)$ 出现的次数,也即 $#\{p(j)=i\}$,考虑怎么维护 $c(i)$ 的变化。

我们知道当 $D=0$ 时,所有 $c$ 都为 $1$。

我们发现,以 $D$ 为横坐标时,$c$ 在一般情况下是先增长,再不变,最后减少的样子(也有可能缺失某一部分)。

增长的话,意味着它向前扩张时没被后面的扩张。

不变的话有两种可能,一种是向前扩张时遇到一个更小的值,并且后面没有把自己扩掉,一种是向前扩张了,但是也被后面的扩张了。

减少的话,意味着没有向前扩张,但是被后面的值扩张了。

如果能预处理出 $c$,就能通过二次差分计算出 $S(D),D=0,1,\cdots,n-1$,现在问题转为对于每一个元素,计算它的 $c$ 函数,我们知道只需求出它的至多的两个拐点。

那我们直接使用单调栈预处理前后比它小的元素,就可以得出 $c$ 了。对于相等的元素,给它定个序就好了。

声明:由于细节过多,该做法暂未实现。

时间复杂度 $O(n)$。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×