[学习笔记] 点分治学习笔记

点分治学习笔记

OI中有一类在树上与路径有关的题目。

如果直接枚举两个端点复杂度至少O(n^2)通常无法承受。

如果考虑枚举路径的LCA通过一些奇技淫巧计算,通常至少需要dfs一遍子树,复杂度依旧无法承受。

因此可以考虑将所有路径分为两类:经过x的和不经过x的。

将经过x的路径全部处理完了之后,相当于是把x去掉,原图变成森林,对每一颗树进行类似做法。

显然如果每一层计算的复杂度是O(n)的话那么最终复杂度取决于层数。

显然希望x的每颗子树不会大于原来的sz的一半,其实就是在求重心。

做法是堆每个点计算其子树最大值,更新即可。

模板:(未编译不知对不对)

int get_rt(int x,int f)
{
	sz[x]=1;maxsz[x]=0;
	for(int i=h[x];i;i=e[i].pre)
		if(e[i].to!=f&&!vis[e[i].to])
		{
			get_rt(e[i].to,x);
			sz[x]+=sz[e[i].to];
			maxsz[x]=max(maxsz[x],sz[e[i].to]);
		}
	maxsz[x]=max(maxsz[x],full_sz-sz[x]);
	if(maxsz[x]<maxsz[rt]) rt=x;
	return 0;
}
int get_sz(int x,int f)
{
	sz[x]=1;
	for(int i=h[x];i;i=e[i].pre)
		if(!vis[e[i].to]&&e[i].to!=f)
			sz[x]+=get_sz(e[i].to,x);
	return sz[x];
}
int calc(int x,int f)
{
	//solve it!
}
int dfs(int x)
{
	rt=0;get_rt(x,0);
	get_sz(x=rt,0);vis[x]=true;
	for(int i=h[x];i;i=e[i].pre)
		if(!vis[e[i].to]) calc(e[i].to,x);
	for(int i=h[x];i;i=e[i].rpe)
		if(!vis[e[i].to]) dfs(e[i].to);
}
int main()
{
	full_sz=n;maxsz[rt]=n+1;
	dfs(1);return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值