直接暴力每颗子树复杂度是O( n 2 n^2 n2)的,树上启发式算法是可以将复杂度优化到O(nlogn)的。
启发式算法是基于人类的经验和直观感觉,对一些算法的优化。
举个栗子:并查集的按秩合并,合并时将秩(集合的高度)小的集合合并到秩大集合上去。
对于树来说也是可以的,不过合并树的话就不能看高度了,而要看树的节点数量,沿用树链剖分的轻重儿子的概念,就是将轻儿子的子树的贡献合并到重儿子的子树上去。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cstdlib>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=100010,M=1e6+10;
int n,a[N],cnt[M][22][2];
int h[N],e[N<<1],ne[N<<1],idx;
void add(int a,int b)
{
e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
int son