Loading

#919. 【UR #28】环环相扣 题解

#919. 【UR #28】环环相扣 题解

取模不好搞,我们先分析性质。

首先可以假设 \(a_i>a_j>a_k\),那么根据“环的顺序”,可以被分成两种情况

  • \(i\to j\to k\to i:(a_i\bmod a_j)+(a_j\bmod a_k)+a_k\)

  • \(i\to k\to j \to i:(a_i\bmod a_k)+a_j+a_k\)

最优化的题,我们可以先分析一个答案下界/上界,与他们的取等条件,这样往往可以找到许多优秀的性质。

分析答案下界是很简单的,就是竭尽所想的构造一个比较优的方案。

分析答案上界需要一些数学手段,得到一种情况的答案上界,若小于等于先前分析的答案下届,那么这种情况就一定是不可取的。

由于取模很复杂,这里直接不考虑取模都可以得到一个答案下界:

考虑第二种情况,有 \(ans\ge a_{\max_2}+a_{\max_3}\),即次大值加次次大值。

根据取模的常见结论:

\(a>b\)\(a\bmod b\le \min(b-1,\frac a2,a-b)\)

得到两种情况的上界:

  • \(ans\le \min(a_j+2a_k-2,\frac {a_i}2+\frac {a_j}2+a_k,a_i,2a_j-1,\cdots)\)
  • \(ans\le \min(a_j+2a_k-1,\frac {a_i}2+a_j+a_k,a_i+a_j)\)

当然对于情况一还有更多的组合,但是形式十分复杂看上去就不怎么好分析。

我们尝试从形式最简单的那几个探究起。

  • 对于第一种情况:

    • \(ans\le a_i\) 这说明当 \(i\) 不取最大值就一定使第一种情况答案达不到上界

    • \(ans\le 2a_j-1\) 这说明 \(a_j\) 只能取次大值(因为 \(a_i\) 是最大值)否则会使答案低于下界

    • \(ans\le \min(a_j+2a_k-2,a_i-a_j+2a_k-1,\cdots)\) 太复杂了,有加减乘除还涉及多个变量,似乎并不能分析出什么。

  • 对于第二种情况:

    • \(ans\le a_i+a_j\):这说明若 \(a_i\) 只能取最大值,否则答案不会更大。
    • 其他情况同理,太复杂了。

现在根据我们的分析重新整理一下两种情况:

  • \(ans=(a_{\max}\bmod a_{\max_2})+(a_{\max_2}\bmod a_k)+a_k\)

  • \(ans=(a_{\max}\bmod a_k)+a_j+a_k\)

可以发现第二种情况 \(a_j\) 不参与任何取模,直接取次大值一定是最优的(之前要求比 \(a_i\) 小,不能贸然得到这个结论)。

于是再次整理为:

  • \(ans=(a_{\max}\bmod a_{\max_2})+(a_{\max_2}\bmod a_k)+a_k\)

  • \(ans=(a_{\max}\bmod a_k)+a_{\max_2}+a_k\)

于是只有 \(a_k\) 是不确定的,单次枚举 \(\mathcal O(n)\),总复杂度 \(\mathcal O(nq)\)。有 \(30\) 分。

如果已经分析了很多性质了,应该尝试一些算法去解决。(分析不出来任何性质也只能套算法呀QWQ)

我们已经把单次查询的复杂度降到最低了(与输入同级了),那么现在要考虑预处理些什么。

发现我们每次其实是在找 \(\max_{k\in [l,r]\setminus\{\max,\max_2\}}\{(a_{\max_2}\bmod a_k)+a_k\}\)\(\max_{k\in [l,r]\{\max,\max_2\}}\{{(a_{\max}\bmod a_k)+a_k}\}\)

可以预处理这两坨。

\(F_1[l][r],F_2[l][r]\) 表示这两坨,尝试整体转移,然后就失败了。

因为 \(a_{\max}\)\(a_{\max_2}\) 是不断变化的,\(F_1,F_2\) 不能继承之前的答案。

这提示我们固定这两个值,有一种神奇的方法

\(F([l,r],i)\) 表示 \(\max_{k\in [l,r]\setminus\{i,\max\}}\{{(a_i\bmod a_k)+a_k}\}\)

然后我们用 \(F([l,i-1],i),F([i+1,r],r)\) 合并出 \(F([l,r],i)\)

这种设 \(F([l,r],i)\) 并处理 \(F([l,i-1]),i),F([i+1,r],r)\) 是一种非常实用的方法,在莫队二次离线中也用了类似的思路。

发现我们可以 \(F([l+1,i-1],i)\to F([l,i-1],i)\)

具体的,设 \([l+1,i]\) 中的最大值下标为 \(t\)

  • \(a_l\le a_t\)\(F([l,i-1],i)=\max((a_i\bmod a_l)+a_k,F([l+1,i-1],i))\)

  • \(a_l>a_t\)\(F([l,i-1],i)=\max((a_i\bmod a_t)+a_k,F([t+1,i-1],i)),t\leftarrow l\)

类似的处理出 \(F([i+1,r],i)\),然后合并出 \(F([l,r],i)\) 注意这里需要特判两边的最大值

复杂度 \(\mathcal O(n^2+q)\)。可以多得 \(10\)

有了新的做法,根据做法分析新的性质(悲

首先发现如果 \([l,i-1]\) 中有两个数大于 \(a_i\) 那么就没必要处理了,因为 \(a_i\) 不会作为这个区间的最大值或次大值。

我们可以在尝试一下答案上下界:\(ans\le a_i\)。当 \(\frac{a_i}2<a_k\le a_i\) 的时候取等,即:若存在两个 \(a_k\) 满足那个不等式也不用搜索了。

假设我们已经知道结论后进一步分析,我们一开始假设从每个 \(i\) 开始,往左/右都恰好走移动两步。如果在 \(k\) 位置要使 \(i\) 的贡献多走一步,\(a_k\) 必定 \(\le \frac {a_i}2\),并且这对于每个 \(i\)不独立的即若存在 \(k<j<i\) 使得 \(j\) 多贡献 \(i\) 一步,\(k\) 多贡献 \(i,j\) 各一部。那么 \(a_k\le \frac {a_j}2\le \frac {a_i}4\)

感性理解,这样只会减小 $\log $ 次。

如果对于每个元素,其运算次数的限制是不独立的,就考虑势能分析

所以要用势能分析,得从运算代价的不独立性考虑。

令势能为 \(a_{\max}^n\) 那么每多移动一步,每多移动一步,其势能就会除以 \(2\)。所以总共多移动 \(\log_2a_{\max}^n=\mathcal O(n\log a)\) 次,算上本来的 \(4n\) 次。预处理复杂度 \(\mathcal O(n\log a)\)

用 ST 表预处理区间最大值可以做到 \(\mathcal O(n\log n+n\log a+q)\)。但是这道题 \(q\)\(n\) 大,用 于是用线段树 \(\mathcal O(n)\) 预处理可以做到 \(\mathcal O(n\log a+q\log n)\)

然而在 UOJ 上只有 \(80\) 分(悲。

可以发现刚刚的答案上界还有另一种形式:\(ans\le 2a_k-1\),也就是说如果存在两个 \(a_u\ge 2a_k\) 那么 \(k\) 就不会成为 \(i\) 的答案位置,因为 \((a_i\bmod a_u)+a_u\ge2a_k>(a_i\bmod a_k)+a_k\)

这与 80 分做法分析的性质很想啊,因为变一下形就是 \(a_k\le \frac{a_u}2\)

考虑如何与刚刚的方法相结合:我想不到,直接引用吧。

  1. 使用 vector<pair<int, long long>> 存储满足 \(F([l, i], i) > F([l+1, i], i)\) 的位置 \(l\),并记录对应的 \(F([l, i], i)\)
  2. 使用一个栈存储尚未被移除的元素。
  3. 针对 \(a_i\) 向左扫描的过程中:
    • 从栈顶到栈底枚举所有元素 \(a_k\)
    • 如果 \(a_k > a_i / 2\),则计数器 cnt++
    • 如果 \(a_k \leq a_i / 2\),则给 \(a_k\) 新增一个删除标记。
    • 如果 cnt 达到 \(2\),立刻停止扫描。
    • 移除累积了两个删除标记的元素。
    • 将具有一个或零个删除标记的元素按照原顺序压回栈中。
  4. 最后将 \(i\) 以初始零个删除标记压入栈中。

这样保证了被个数计算次数不超过 \(4\)。扫描长度总和 \(\mathcal O(n)\)

考虑这种不用额外性质却需要同时结合多个性质的算法设计,需要一气呵成,然后调整。这需要多练习积累正确的方向与感觉。

最后复杂度 \(\mathcal O(n+q\log n)\)\(100\) 分。

posted @ 2025-02-25 21:09  lupengheyyds  阅读(43)  评论(0)    收藏  举报