A11【模板】树上差分

相关板子:
D09 倍增算法 P3379【模板】最近公共祖先(LCA) - 董晓 - 博客园
P3128 [USACO15DEC] Max Flow P - 洛谷
// #include<bits/stdc++.h> using namespace std; const int N=50005,M=2*N; int h[N],to[M],ne[M],tot; void add(int x,int y){ to[++tot]=y,ne[tot]=h[x],h[x]=tot; } int n,m,ans,power[N]; int dep[N],f[N][22]; void dfs(int x,int fa){ dep[x]=dep[fa]+1,f[x][0]=fa; for(int i=1; i<=20; i++) f[x][i]=f[f[x][i-1]][i-1]; for(int i=h[x]; i; i=ne[i]){ int y=to[i]; if(y!=fa) dfs(y,x); } } int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); for(int i=20; ~i; i--)if(dep[f[x][i]]>=dep[y]) x=f[x][i]; if(x==y) return y; for(int i=20; ~i; i--)if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } void dfs2(int x,int fa){ for(int i=h[x]; i; i=ne[i]){ int y=to[i]; if(y!=fa){ dfs2(y,x); power[x]+=power[y]; //差分的子树和 } } ans=max(ans,power[x]); } int main(){ scanf("%d%d",&n,&m); for(int i=1,x,y;i<n;++i){ scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs(1,0); //倍增预处理 dep,fa 数组 for(int i=1,x,y; i<=m; ++i){ scanf("%d%d",&x,&y); int z=lca(x,y); //倍增求lca ++power[x];++power[y]; --power[z];--power[f[z][0]]; //树上点差分 } dfs2(1,0); //统计答案 printf("%d\n",ans); }
练习:
P10931 闇の連鎖 - 洛谷 U143800 暗之连锁 - 洛谷
Luogu P2680 [NOIP2015 提高组] 运输计划
Luogu P1600 [NOIP2016 提高组] 天天爱跑步
浙公网安备 33010602011771号