咸鱼学妹大战树分治(点分治、点分树)
陈年笔记,现在可能不会了。
点分治
Q1:基本思想是什么?
将路径分为经过
Q2:如何统计?
- 一般:遍历
的每个子节点 ,把 子树内的节点记录下来,得到答案并更新数组。 - 容斥:把
子树内的节点都记录下来排序,双指针得到的 子树内点对数量,减去每个子节点 子树内的点对数量,即为经过 的路径的答案。*
Q3:如何保证复杂度?
每次
Q4:用途是什么?
统计树上满足条件的路径(点对)个数(或点权和等),一般条件和距离相关。
void findrt(int u,int f){
siz[u]=1;
maxp[u]=0;
for(int i=fir[u];i;i=nex[i]){
int v=to[i];
if(vis[v]||v==f) continue;
findrt(v,u);
siz[u]+=siz[v];
maxp[u]=max(maxp[u],siz[v]);
}
maxp[u]=max(maxp[u],sum-siz[u]);
if(maxp[u]<maxp[rt]) rt=u;
}
void dfz(int u){
vis[u]=1;
//计算!!!
for(int i=fir[u];i;i=nex[i]){
int v=to[i];
if(vis[v]) continue;
rt=0;
sum=siz[v];
findrt(v,u);
dfz(rt);
}
}
边分治
其实和点分治差不多。
点分树
Q1:基本思想是什么?
通过点分治的方法递归,每次的得到
Q2:特殊性质?
- 最多
层。 - 重构树上的 LCA(x,y) 必定在原树 x 到 y 的路径上,有
。*
Q3:如何运用特殊性质?
点分树又被成为动态点分治。
点分树和点分治一样适用于统计满足条件的路径的点权和,但点分树可修改点权,更加灵活,保证了每次只需查询或修改
Q4:具体实现?
- 得到重构树,其实只需记录
。 - 一个显然的思路是在重构树中将
不断变为父亲节点,得到在 子树内但不在 子树内的贡献。 - 想想如何更新。我们用
存 子树中 的数据, 存 子树内 的数据。
示例:P6329 【模板】点分树
void modify(int x,int k){
int now=x;
while(now){
F.modify(now,getdis(now,x),k);
if(Fa[now]) G.modify(now,getdis(Fa[now],x),k);
now=Fa[now];
}
}
int query(int x,int k){
int now=x,pre=0,ret=0;
while(now){
int t=getdis(now,x);
if(t>k){
pre=now,now=Fa[now];
continue;
}
ret+=F.ask(now,k-t);
if(pre) ret-=G.ask(pre,k-t);
pre=now,now=Fa[now];
}
return ret;
}
本文来自博客园,作者:咸鱼学妹,转载请注明原文链接:https://www.cnblogs.com/zhangtj/p/18359675,不然会AFO
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】