【题解】Solution Set - NOIP2024集训Day13 点分治、点分树

【题解】Solution Set - NOIP2024集训Day13 点分治、点分树

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


「COCI 2018/2019」Deblo

\[\sum_{i=1}^n\sum_{j=i+1}^nw_i\oplus w_j\oplus a_{\text{lca}(i,j)} \]

看到异或就想到拆位。对于第 \(j\) 位。

如果 \(a_{\text{lca}(i,j)}\)\(1\),就是要在子树里面找两个当前位都为 \(1\) 的对数(为 \(0\) 同理),直接 dsu on tree 或者 点分治 就行了。(实际上也不需要,每个子树实际上只用开 \(2\log V\) 的空间,合并的时间复杂度相同,所以可以直接存下来。(dsu 甚至还多带一个 \(\log\)


「Hdu6643」Ridiculous Netizens

看到乘积,想到根号分治。

对于当前新加入的点的权值 \(a\)

如果:

  1. \(a> \sqrt m\),那么 \(\dfrac ma<\sqrt m\),我们只需要记录乘积小于 \(\sqrt m\) 的那部分。
  2. \(a\le \sqrt m\),那么对于每一个这样的 \(a\) 我们可以知道最大满足和她相乘小于等于 \(m\) 的值,而这样的值最多有 \(\sqrt m\)​ 个,所以直接存起来就好了。

Motivation:选取关键点 dp,减小时空。


跑一遍乘积和小于等于 \(x\) 的依赖于父亲的树背包。

或者转化到 dfn 序上 dp,具体可以参见:https://blog.csdn.net/Emm_Titan/article/details/121255055


image


「ZJOI2015」幻想乡战略游戏

题意:求带权重心。支持动态修改权值。


考虑单个询问怎么做。

先随机走到一个点 \(u\),考虑她的一个儿子 \(v\),边权为 \(w\)\(f_i\) 表示 \(i\) 的子树内 \(d\) 的和,\(sum\) 为整体 \(d\) 的和。

那么我们用 \(v\) 代替 \(u\) 的充要条件为:

\[-w\times f_v+w\times (sum-f_v)<0\\ \Leftrightarrow 2f_v>sum \]

(实际上一般的不带权的树重心也是这样推的。

显然我们不会走回头路,所以一旦我们往一个儿子走了,其她的儿子都没用了。

所以一旦走到一个儿子又是一个子问题

可以发现,答案的决策和边权并没有关系,也就是跟树的形态没有关系。

所以我们可以直接点分树。

但是我们不能像暴力那样直接算走过一条边之后答案的变化量,因为现在是走过的一条链,而链上面还要很多点,没法直接算贡献。

然后不会了。


好吧,正常的点分树就和度数有关了……因为题目保证了度数小于等于 \(20\) 所以我们暴力给每个儿子算答案,然后往会变小的那边走就行了。

每次算答案的话其实是一个点分树的典问题(【模板】点分树 | 震波 这应该算是加强版了),就是维护两个东西:

  1. \(x\) 子树中所有 \(d\)\(x\) 的贡献;
  2. \(x\) 子树中所有 \(d\)\(x\) 的父亲(点分树上)的贡献。

听说可以通过三度化,然后整个算法跟度数无关?

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