点分治这个算法听了一年了,最近没有比赛就学了一下。
题面
题意:给你一棵树,问距离小于等于L 的点对有多少个。
点分治定义了一个叫重心的点。即是割去它后最大的连通块最小的点。然后有证明最大的连通块大小不大于总点数的一半。
对于这题,先找到重心x,然后要处理的便是经过点x的路径。可以用dfs求出所有点到x的距离,然后排序,单调寻找点对。
若有两个点来自同一个连通块,它们分别到x的距离的和小于等于L,我们也把它们算了进去,故还要减去这一部分。
然后递归处理每个连通块即可。
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define mmst(a, b) memset(a, b, sizeof(a))
#define mmcp(a, b) memcpy(a, b, sizeof(b))
typedef long long LL;