【题解】CF246E Blood Cousins Return(树上查询K-Son)
题意
给定一片 \(n\) 个点的森林,每个节点有一个名字。
\(m\) 次询问,每次询问一个节点的 \(K-Son\) 共有个多少不同的名字。一个节点的 \(K-Son\) 即为在该节点子树内的,深度是该节点深度 \(+K\) 的节点。
\(n,m\le 10^5\)。
我的沙笔莫队做法
找到一个点 \(x\) 的 \(K-Son\),相当于找到深度为 \(dep[x]+K\) 且在 \(x\) 子树中的点。
在 \(x\) 的子树中可以用 \(dfn\) 序进行限定。因此我们现在有 \(2\) 个限制:\(dep\) 和 \(dfn\)。
考虑将所有深度一样的点放入一个 \(vector\),并将所有 \(vector\) 按照 \(dfn\) 从小到大排序。则任意一个点的所有 \(K-Son\) 在某个 \(vector\) (其对应深度为 \(dep[x]+K\))中的连续一段。
问题就变成了,给定 \(m\) 个询问,每次询问一个深度中,其 \(vector\) 的连续一段中有多少不同的名字。
注意到如果只有一个深度,那我们就可以用莫队摆平它。现在有至多 \(n\) 个深度,所以我们对所有深度都做一遍莫队即可。
设 \(vec[d]\) 为存储深度为 \(d\) 的点的 \(vector\),它的大小为 \(siz_i\)。块长取 \(\sqrt{\max siz_i}\) 可以通过,时间复杂度为 \(O(\sum\limits_{i} siz_i\sqrt{siz_i})\)
也许可以卡?但是应该不好卡,我没卡掉。而且实测只跑了530 ms,现在是Rank 6。
细节有点多,主要是在处理莫队指针移动的地方。
提交记录:https://codeforces.com/contest/246/submission/163660600