NOI2016 王国饮水记

NOI2016 王国饮水记

如何不写斜优/决策单调性,用暴力通过此题。。(大雾)

首先我们只需要考虑 \(h_i>h_1\) 的点。

然后考虑 \(K\) 足够大的点,我们手玩一段时间,发现将这些剩余点保留下来并排序,最优决策一定是将他们依次和 \(1\) 联通。

比如样例中的 \(1,3,4\),假设可以操作 \(2\) 次及以上,那么最优决策一定是依次连接 \(1,3\) 得到 \(2\),然后连接 \(2,4\) 得到 \(3\)

对于 \(K\) 并非足够大的点,先将剩余点从小到大排序,不难发现每次的连通操作必然是将 \(1\) 和一段区间 \([l,r]\) 联通,同时不存在一个点被连两次(显然不优)

感性上理解大概可以通过调整法,知道这个性质之后我们可以写一个 Dp 了:(方便起见,下文的 \(h\) 数组是仅保留大于 \(h_1\) 的元素且已经排好序,下标从 \(2\) 开始的数组,而 \(S\) 为其前缀和)

\(f_{i,j}\) 表示考虑到 \([2,i]\),操作了 \(j\) 次的最优解,那么转移形如 \(f_{i,j}=(f_{k,j-1}+S_i-S_k)/(i-k+1)\)

然而要进行高精度小数运算,我们得到了一个 \(\mathcal O(n^2Kp)\) 的做法,非常幸运的是他可以过 \(n\le 100\) 的测试点。

然后我们将最优决策打个表,会发现大概是这样的例子(以样例 \(3\) 为例)

[100, 100]
[99, 99]
[98, 98]
...
[65, 66]
[62, 64]
[50, 61]

然后发现好像长度不是 \(1\) 的区间非常少?而且决策应该是从某个位置开始的后缀,都会被选中。

我们大胆猜测长度不为 \(1\) 的区间只有 \(\log\) 个(实际上是调参之后知道的),于是 Dp 的第二个维度可以降低成 \(\log\),便得到了一个 \(\mathcal O(n^2\log np)\) 的做法。(大概是预处理 Dp 数组,然后枚举之前用了多少次,然后剩余部分一直除以 \(2\)

然后造一点随机数据,继续打表,然后发现最大的区间的长度也很小?

于是转移的时候 \(k\) 的枚举量不需要到 \([1,i]\),只需要到 \([i-c,i]\) 即可,\(c\) 为一个常数。

于是得到了一个 \(\mathcal O(n\log n\times c\cdot p)\) 的做法。

然后我们发现,之所以需要高精度小数,是因为我们经常除以 \(x\),而且除以次数高达 \(K\) 次,然而如果只考虑预处理部分的 \(O(n\log n\times c)\) 的 Dp,我们发现我们只会除以 \(\log\) 次,换而言之没有必要用高精度小数。。。

于是这个部分用 long double 把答案存下来来比较(当然误差很大但是不影响),然后我们将决策点记录下来,最后还原答案的时候通过高精度实现即可。

最终复杂度是 \(\mathcal O(n\log n\times p+n\log n\times c)\),跑得非常快,我的 \(c\) 设的是 \(100\),是可以通过的。

正常的做法应该是考虑:

\[\frac{dp_j+S_i-S_j}{i-j+1}<\frac{dp_k+S_i-S_k}{i-k+1} \]

对于每个点 \(j\)\(k\) 我们将其视为 \((j-1,dp_j-S_j)\),那么不难发现这个是最大的 \((i,S_i)\) 与点集 \(S\) 中的斜率最大值。

可以三分交点解决。

posted @ 2020-09-11 19:38  Soulist  阅读(101)  评论(0编辑  收藏  举报