CF1827
CF1827
A. Counting Orders
简单计数。
两个都排序,双指针维护一下 a[i]
在 b[p]
的位置(a[i] <= b[p]
)。
那么方案数 。
提交:https://codeforces.com/contest/1827/submission/211387552
C. Palindrome Partition
回文好题。
考虑利用 Manacher
求出每一个偶数的回文串。
观察可以发现:每一个合法的串都可以被划分为多个最小的合法串,并且划分方法是唯一的。
所以考虑如下:
我们需要维护出每一个点作为右端点,最靠近的左端点。
这等价于求出满足 ,求 。
-
做法1:利用上面的限制,可以通过
ST
表求解。 -
做法2:由于需要中心最大,所以逆序处理,利用每一个中心更新没有更新过的点。
由于每一个点只需要更新一次,考虑使用链表或者并查集维护。我用的是并查集。
然后,设上面对于端点 求出来的结果为 。
得出最终的递推式:
其中 表示以 结尾的合法的串的个数。
最终的答案为 。
提交:Submission #211396680 - Codeforces
D. Two Centroids
性质好题。
重心有如下性质:
-
最大子树大小 。
-
新增一个叶子节点,重心最多变化一条边。
-
重心至多有两个。
那么我们考虑每次加入一个点对于原来重心 的影响,并设当前最小的子树大小为 。
-
如果加入的叶子节点在 的子树 内。更新 的大小,并更新 。如果此时 ,那么重心向 移动。并且此时 更新为 (
不考虑,把图画出来就明白了。 -
由于我们不可能动态维护以每一个重心为根,所以还要考虑其祖先的情况(同理)。
然后就是如何找 的问题。有两种解决方案:
-
无论如何首先可以通过
dfn
序判断是否在其子树内。-
方案1:利用倍增的方法跳祖先。空间复杂度 ,单次 。
-
方案2:利用
dfn
区间,对于每一个节点保存其子节点的dfn
,每次二分找到叶子的dfn
所在的区间即可。(我用的这种方法)空间 ,单词 。
-
-
实测第二种要快一点点(也快不了多少,主要是常数够好)
提交:Submission #211401150 - Codeforces
E. Bus Routes
差点没用 dlang 卡过去
思路1
考虑更严的限制(等价):叶子节点间两两可以在两次内到达。
于是考虑对于每一个叶节点,求出其能到达的最高的祖先 。
也就是求一个
LCA
即可。
那么满足条件的必要条件是每一对 满足祖先/子节点关系。
如果不是,那么至少需要三条路径。
如果满足上述条件,那么所有的 满足在一条链上。
那么可以通过
dfn
序判断。
这并不充分。
考虑找到最低那个 ,并以 作为根。
此时重新求一次 ,如果所有的 都为 ,那么就是 的,否则,如果有 ,那么 不可达。
不要写倍增求 LCA,利用 ST表 或者 树链剖分 ,甚至是离线 求。倍增太慢了,dlang 卡不过去。
思路2
参考 Alex_Wei
的博客:https://www.luogu.com.cn/blog/_post/575397。
利用 DSU on tree
。
思路3
维护虚树并树上差分。非常的高效。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App