loj 3637 题解

loj 3637 题解

一些猜想

考虑假设当前要计算 \(ans_{i}=\max_{a}\sum_{l,r}[\operatorname{mex}({a_{x}|x\in[l,r]})\ge i]\)

也就是说要让最多的区间包含 \([0,i-1]\) 的数字。

也就是要让最少的区间不完全包含 \([0,i-1]\) 的数字。

一个想法是把 \([0,i-1]\) 这些数分成若干组,每组之间可以插入一些数字。

这个想法来源于 \(i=1\) 的情况,我们要用 \(0\) 把序列分割成若干段,假设第 \(i\) 段的长度是 \(d_{i}\),我们要让 \(\sum\frac{d_{i}(d_{i}+1)}{2}\) 尽可能小。

至于这个想法为什么在 \(i>1\) 的时候仍然成立,我们稍后证明。

因为小于 \(i\) 的数字和大于等于 \(i\) 的数字内部地位相同,我们不妨令 \(cnt[0]\ge cnt[1]\ge \dots cnt[i-1]\),并把大于等于 \(i\) 的数字记作 \(X\)

简单情况

先考虑一个一般的情况,\(cnt[0]=cnt[i-1]\)

我们最终的序列长这样 \(X\dots X012\dots(i-1)X\dots X012\dots(i-1)X\dots\)

记每一段 \(X\) 的长度为 \(d_0,d_1,\dots,d_x\)(设 \(x=cnt[0]\)),那么答案是:

\[S(n)-((x-1)\times i+1)\times (i-1) - S(i-1)-\sum_{i=0}^{x}\left(S(d_{i})+([i>0]+[i<x])\times (p-1)\right) \]

其中 \(S(x)=\frac{x(x+1)}{2}\)

这个的解释就是:所有区间 - 所有 \(012\dots(i-1)\) 段内部以及之间的贡献(画图理解,这一段的某个点开始一直延伸到下一段这个点之前两个的位置都可以,但是最后一段没有下一段了要特殊考虑) - 对于每一段 \(X\),内部有一个 \(S(d_i)\) 的贡献,可以往前面一段(如果有)和后面一段(如果有)延申 \(p-1\) 的贡献。

证明

我们简单证明一下为什么最终结果 \(0\sim(i-1)\) 每一组都一定相邻:如果不相邻,那么中间的 \(X\) 可以多往外延申很多,即 \(\dots XX12\dots XX\dots (i-1)XX\dots\),你发现把 \(X\) 提到右边或者左边后(假设右边),中间与右边的 \(X\) 组成的区间数量不变,但是少了左边的区间的贡献(其实很严谨的,但是表述出来有点感性,建议画图+调整法理解,我能保证这个结论是对的)。

拓展到一般情况

有了上面的证明,我们考虑当 \(cnt[0]>cnt[i-1]\) 的时候,最后会剩下一段 \(012\dots,j(j<i-1\and cnt[0]=cnt[1]=\dots=cnt[j]>cnt[j+1]=\dots=cnt[i-1])\)。有结论:这一段必然接在前面某一个整段的后面

证明:如果这一段与某一个整段之间有 \(X\),那么把这些 \(X\) 拉出来之后显然更优。证明与上面的类似。

还有一个结论:中间第 \(1\sim x -1\) 段的地位相同,据调整法有他们尽可能每一段长度相等的时候最优,证明简单。同理,最左边和最右边两段的地位也相同,他们也应该有相近的数量

计算答案

所以,一个很暴力的想法就是枚举最左边和最右边的点数,中间的贪心算(\(\Omicron(1)\))。

观察答案公式:

\[S(n)-((x-1)\times i+1)\times (i-1) - S(i-1)-\sum_{i=0}^{x}\left(S(d_{i})+([i>0]+[i<x])\times (p-1)\right) \]

\(c=\sum d_{i}\),则,原公式等价于:

\[S(n)-((x-1)\times i+1)\times (i-1) - S(i-1)-\sum_{i=0}^{x}S(d_{i})-(2c-d_0-d_x)\times(p-1) \]

我们发现,随着左右两边的 \(d_0+d_x\) 逐渐增大,答案减少量逐渐变小,最后答案逐渐增大(因为 \(S(d_0)+S(dx)-(p-1)(d_0+d_x)\) 是一个凸函数嘛)。

所以可以二分,并且把 \(d_0=d_x\)\(|d_0-d_x|=1\) 两种情况都算一遍就行。

卡常小技巧:再观察发现随着 \(i\) 增大,\(c\) 逐渐减小,\(d_0,d_1\) 也逐渐减小,证明比较简单,因此可以在 \(d\) 较小的时候放弃二分,直接双指针。但是有一个分界点是 \(x=X+1\) 变成 \(x=X\) 的时候,这个地方特判然后重新给 \(d_0,d_1\) 赋值()。(可能这一部分有问题,我没有仔细证明)。

后记

loj 上面的数据挂了,记得读入第二行字符串的时候把个数修改为 \(m\) 个。

posted @ 2023-03-13 20:12  lazytag  阅读(73)  评论(2)    收藏  举报