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

来源:互联网 发布:淘宝宜家代购是真的吗 编辑:程序博客网 时间:2024/05/17 06:58

点分治学习笔记

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;}


原创粉丝点击