【题解】Solution Set - NOIP2024集训Day7 线段树分裂与合并、平衡树

【题解】Solution Set - NOIP2024集训Day7 线段树分裂与合并、平衡树

https://www.becoder.com.cn/contest/5449


「湖南集训」更为厉害

原题 - 谈笑风生

sizx 为子树 x 的大小,sumx 为子树 x 中节点的 sizx1 之和。

Ans=ysubtree(x)1dis(x,y)k(sizy1)+(sizx1)×min(depx1,k)

然后考虑线段树合并,把一棵子树上的信息存在一棵线段树上,下标是距离,但是线段树的信息不能平移啊。好的破产。


考虑按照 dep 建一棵主席树,然后查询 dfn[x]dfn[x]+siz[x]1 的就好了。


又去看了一下题解,线段树合并还是可以做的,下边不存相对距离,而存绝对距离,就是 dep 就好了。


「PKUWC2018」Minimax

首先所有权值都有可能被取到,所以式子的前两项都很好处理。

现在问题是算出每个权值分别概率就解决问题了。

先离散化一下。

考虑 dp。初始值 fi,j=1i 为叶子节点,j 是她的权值。g(j) 表示在当前 i 的子树中,权值 j 对应的是 i 的那个儿子。

fi,j=fg(j),j×(pi×yson(i)\g(j)k=1j1fy,k+(1pi)×yson(i)\g(j)k=j+1nfy,k)

关键信息是一个节点至多有两个儿子。

bf

现在就是要用 ds 去优化这个 dp。

直接线段树合并好了,为了规避掉代码中很烦人的判 x,y 的地方,我们直接分别把左右儿子当成 x 算一遍,再加起来(不合法的那一个 f0,最后对当前位置的贡献也是 0


但是很难处理前后缀和的信息。

于是去请教了一下 cube,实际上的做法是:

在线段树合并的时候,维护后面括号那一坨,然后递归的单个节点的时候,打上乘法标记。

怎么维护后面那一坨?

我们在线段树上面维护区间和,每次合并左右儿子的时候,就计算左右儿子分别对对方的贡献。

因为我们是递归合并,所以必须有一个先后顺序,注意需要提前记录一下。


「POI2011 R2 Day2」旋转树木 Tree Rotations

每次相当于合并两棵子树,考虑在合并的时候计算这两个子区间的贡献,取交不交换的最大值就好了。

具体的,和上面 「PKUWC2018」Minimax 这道题很类似,每次合并的时候维护每个元素在另一棵树上比她大的有多少个,然后把总和加起来。


「TJOI / HEOI2016」排序

之前做过。

如果权值过大很难动态维护排序的过程,但是如果权值只有 0/1,那就可以直接分前后连段线段树赋值就好了。

我们考虑二分答案,check 的时候将每个权值重新赋值为 [aimid],最后只需要看 q 这一位如果是 1 说明可以更大,否则更小。

总时间复杂度:O(nlog2n)

posted @   CloudWings  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示