析合树建树

以前一直只写过析合树计数但没见过建析合树的代码。前几天刚好碰到一个就把我的建法补在这里了。

以下称对于所有“区间 [l,r]”的称呼都默认“pl,pl+1,,pr 的值形成连续段”。

考虑分治,假设现在分治到区间 [l,r],如果 l=r 那么直接 return 即可。否则考虑怎样判断一个区间 [l,r] 是合点还是析点。考虑 p 为最靠左的满足 [p,r] 是区间的位置,那么有 [l,r] 是合点当且仅当 [l,p1] 是区间,这个可以有析点和合点的定义得出。

接下来考虑怎么找出这个区间的所有儿子,还是分这个区间是析点和合点考虑:

  • 如果这个区间是合点,那么我们第一次找到的这个 [l,p1] 肯定是这个区间的第一个儿子,那么对于后面的部分,我们就不断在 [p+1,r] 中二分找到最左的 p 满足 [p,r] 是一个区间,然后将 [p,p1] 设为下一个儿子然后继续向后找即可。有一个注意点,就是我们有可能找到的 [p,r][l,r] 最右边的儿子的某个儿子(画个图可能比较好理解),不过根据析合树的性质,跨层的连续段肯定不是区间,因此这种情况的 [l,p1] 肯定不是区间,直接将这个作为终止条件即可。
  • 如果这个点是析点,那么我们第一次找到的这个 [p,r] 肯定这个区间的最后一个儿子,这次改成从右往左找到所有儿子即可。同理,我们有可能有一次二分到的 p[l,r] 第一个儿子的儿子节点,解决方法是如果 [l,p1] 是区间,那么说明我们已经跳到了区间 [l,r] 的第一个儿子,break 掉即可。

现在我们需要进行的操作是找到 [l,r] 中最左的 p 满足 [p,r] 是区间。这是一个很 sb 的问题。直接将数区间问题的线段树改成主席树,然后在 r 对应的主席树上二分最左端的 0 的位置。

时间复杂度仍然是 1log 的。

posted @   tzc_wk  阅读(109)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示