点分治学习笔记

发布时间 2023-06-30 16:04:02作者: Code_AC

参考蓝书发篇学习笔记。。。

一.算法梗概:

点分治是一种用于在一棵树上,无对路劲进行修改的操作,对某些具有限定条件的路径进行静态统计的算法。
点分治一般用来处理无根树,我们可以随意认定根节点。

二.实现过程:

我们拿一道例题来说一下:

P4178 Tree

我们认定根节点为 \(root\),那么对于 \(root\) 而言,树上的路径有两种:
1.经过 \(root\) 的路径;
2.不经过 \(root\) 但包含在 \(root\) 的某棵子树内。

对于路径种类1,我们可以从 \(root\) 点出发,对整棵树进行 \(\text{dfs}\),求出点 \(i\)\(root\) 的距离 \(dis_i\),同时可以求出 \(b_i\),表示 \(i\) 属于 \(root\) 的哪一棵子树。特别地,\(b_{root}=root\)

代码如下:

点击查看代码
inline void getdis(int x,int fa,int d,int from)
{
    a[++now]=x,b[x]=from,dis[x]=d;
    for(int i=head[x];i;i=e[i].nxt)
    {
        int y=e[i].to,z=e[i].len;
        if(y==fa || vis[y]) continue;
        getdis(y,x,d+z,from);
    }
    return;
}

而我们要统计的,就是满足如下所有条件的点对 \((x,y)\) 的数量:(1)\(b_x\ne b_y\);(2)\(dis_x+dis_y\leqslant k\)

对于路径种类2,我们可以分治一下,将 \(root\) 的每棵子树递归处理。

那么我们最常见的 \(calc\) 函数的写法,就是指针扫描数组的方法