Live2D

Solution Set -「ABC 217」

  大家好屑兔子又来啦!


【A - Lexicographic Order】

  说个笑话,WalkingDeadOneInDark 在这题各罚了两次时,我因为不会所以没有被罚。

【B - AtCoder Quiz】不会。

【C - Inverse of Permutation】不会。


【D - Cutting Woods】

  我本来不会的,但上次都是从 D 开始讲的所以就……

  用 std::set 维护切割点,标记 x 所在段的长度就是它在集合里的后继减去前驱。


【E - Sorting Queries】

  讲个笑话,我以为 std::merge 的复杂度是较短容器的长度。

  基础的势能算法吧,用 std::multiset 维护前缀有序段,用队列维护其他无序元素。进行排序操作时暴力把队列全部塞到 set 里即可。


【F - Make Pair】

  讲个笑话,我一度想要优化一个睿智的 O(n4) DP。

  看到“相邻配对删除”,应该想到区间 DP,并且利用“在某一时刻相邻而现在不相邻”这一条件将序列划分为独立子问题。

  令 f(l,r) 表示将区间 [l,r] 内的人全部配对的方案数(那么自然需要 2(rl+1))。转移时枚举与 l 配对的人 i,得到转移

f(l,r)=i(l,r],2(il)((rl+1)/2(ri)/2)f(l+1,i1)f(i+1,r).

其中有边界 f(i,i+1)=1。组合数对应这个计数场景:“左边有 a 次操作,右边有 b 次操作,(l,i) 还有一次配对操作,且必须在左边 a 次完成后进行”,那么把这一次归类为第 a+1 次左边操作,方案数即为 (a+1+bb)。复杂度为 O(n3)


【G - Groups】

  为什么 G 永远比 F 简单,永远是计数问题,永远存在更优秀的多项式算法。(其实上次就不是。

  还是想象成把球(人)放进盒子(组)里会比较舒服。我们忽略掉题目中要求“盒子相同”“盒子非空”的要求之后,会发现此时的方案数就是组合数的若干次方。具体地,我们能求得 fi 表示将这些球放进至少 i 个盒子里,且非空的盒子本质不同的方案数,有

fi=(Ain/m)m(nmodm)(Ain/m+1)nmodm.

其中 Anm=(nm)m!n 个里选 m 个排列的方案数,n<m 时值为 0

  此后,令答案为 gi,根据组合意义(我当时随便凑了几个式子过样例就交了√),可以得到 g 的表达式

gi=fij<iAijgj.

由于是 ABC,直接递推出这个东西就可以 O(n2) 求解了。

  不过,显然可以用分治 FFT 优化至 O(nlog2n)。我写出来大概是十倍速度。但是最优解貌似是 O(nlogn),仅用一次卷积的做法,有空研究√

  UPD: 谢谢,移项之后就是 exG=F 了,确实可以直接卷,我是屑。


【H - Snuketoon】

  令 fi(x) 表示前 i 次射击后,站在 x 位置,受到的最小伤害。注意水枪伤害的性质,我们断言 fi(x) 的是下凸的。虽然不难证明,但的确是本题的重点。

  所以,可以用两个 std::multiset 维护左半凸壳和右半凸壳的转折点,并保证转折点两侧的斜率差为 1(所以需要维护重点)。那么转移过程中,我们需要完成一次整体取邻域最小值和叠加一段斜率为 ±1 的一次函数。维护一下就好√

posted @   Rainybunny  阅读(122)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示