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

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

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


「湖南集训」更为厉害

原题 - 谈笑风生

\(siz_x\) 为子树 \(x\) 的大小,\(sum_x\) 为子树 \(x\) 中节点的 \(siz_x-1\) 之和。

\[Ans=\sum_{y\in subtree(x)\wedge 1\le dis(x,y)\le k}(siz_y-1)+(siz_x-1)\times\min(dep_x-1,k) \]

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


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


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


「PKUWC2018」Minimax

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

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

先离散化一下。

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

\[f_{i,j}=f_{g(j),j}\times\left(p_i\times\prod_{y\in son(i)\text{\\}g(j)}\sum_{k=1}^{j-1}f_{y,k}+(1-p_i)\times\prod_{y\in son(i)\text{\\}g(j)}\sum_{k=j+1}^{n}f_{y,k} \right) \]

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

bf

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

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


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

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

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

怎么维护后面那一坨?

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

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


「POI2011 R2 Day2」旋转树木 Tree Rotations

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

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


「TJOI / HEOI2016」排序

之前做过。

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

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

总时间复杂度:\(O(n\log^2 n)\)

posted @ 2024-08-14 08:34  CloudWings  阅读(22)  评论(0编辑  收藏  举报