To_Heart—总结——点分治

哈哈哈哈没想到吧学了四年OI年点分治都不会!

主要记录一下点分治的思路。代码实现能力不行但是一定要锻炼口胡能力!

首先一般实现三个个函数。

开始前先明确用 vis 数组和 fa 节点来确保遍历的是当前子树。

第一个函数是寻找当前子树的根节点。先存一下整个子树的size记作 sum 再利用重心的性质,即重儿子的size>(子树的size/2) 注意这里的儿子包括先前的节点,也就是 (sum-sz[x]) 。

第二个函数是查询&修改,也就是利用先前的信息更新当前的答案。注意到只算不同于当前子树的答案,内部的答案分治下去讨论。也就是先查询再修改。

第三个是递归函数,也是solve主函数,主要是传进当前子树的重心然后查询&修改并向下递归。

注意到很多时候点分治的使用跟距离联系密切,所以还有一个函数在查询&修改中使用,目的是预处理当前子树的dis。

大概的执行思路长这样子:

void solve(int u){
	vis[u] = pd[0] = 1, doit(u);
	Next(i, u){
		int v = e[i].v;
		if(vis[v]) continue;
		dp[0] = n, sum = size[v], root = 0;
		getroot(v, u), solve(root);
	}
}

随便扒的代码。能看懂就行了。

你可能感兴趣的:(算法,数据结构)