D34【模板】长链剖分 CF1009F Dominant Indices
视频链接:333 长链剖分【模板】CF1009F Dominant Indices_哔哩哔哩_bilibili
Luogu CF1009F Dominant Indices
// 长链剖分+树形DP #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; const int N=1e6+5; vector<int> e[N]; int n,son[N],len[N]; int buf[N],*f[N],*p=buf,ans[N]; //f[x][i]:在x子树内与x的距离为i的节点数 void dfs(int x,int fa){ //长链剖分 for(int y : e[x]){ if(y==fa) continue; dfs(y,x); if(len[son[x]]<len[y]) son[x]=y; } len[x]=len[son[x]]+1; } void DP(int x,int fa){ //树形DP f[x][0]=1; if(son[x]){ f[son[x]]=f[x]+1; //共享内存,f[son[x]][i]会被自动保存到f[x][i+1] DP(son[x],x); ans[x]=ans[son[x]]+1; //继承答案 } for(int y : e[x]){ if(y==fa||y==son[x]) continue; f[y]=p; p+=len[y]; //给y开头的链分配内存 DP(y,x); for(int j=1; j<=len[y]; j++){ f[x][j]+=f[y][j-1]; //暴力合并 if(f[x][j]>f[x][ans[x]] || f[x][j]==f[x][ans[x]] && j<ans[x]) ans[x]=j; //更新答案 } } if(f[x][ans[x]]==1) ans[x]=0; //修正 } int main(){ scanf("%d",&n); for(int i=1; i<n; i++){ int x,y; scanf("%d%d",&x,&y); e[x].push_back(y); e[y].push_back(x); } dfs(1,0); f[1]=p; p+=len[1]; //给树根长链分配内存 DP(1,0); for(int i=1;i<=n;++i) printf("%d\n",ans[i]); }
练习:
Luogu P5904 [POI2014] HOT-Hotels 加强版
#include<cstdio> #include<algorithm> #include<cstring> #include <vector> using namespace std; #define LL long long const int N=100005; vector<int> e[N]; int n,len[N],son[N]; LL buf[N<<2],*f[N],*g[N],*p=buf,ans; void dfs(int x,int fa){ //长链剖分 for(int y : e[x]){ if(y==fa) continue; dfs(y,x); if(len[son[x]]<len[y]) son[x]=y; } len[x]=len[son[x]]+1; } void DP(int x,int fa){ //树形DP f[x][0]=1; if(son[x]){ f[son[x]]=f[x]+1; g[son[x]]=g[x]-1; DP(son[x],x); } ans+=g[x][0]; for(int y : e[x]){ if(y==fa||y==son[x]) continue; f[y]=p; p+=len[y]<<1; g[y]=p; p+=len[y]<<1; DP(y,x); for(int j=0;j<len[y];++j){ if(j) ans+=f[x][j-1]*g[y][j]; ans+=g[x][j+1]*f[y][j]; } for(int j=0;j<len[y];++j){ g[x][j+1]+=f[x][j+1]*f[y][j]; if(j) g[x][j-1]+=g[y][j]; f[x][j+1]+=f[y][j]; } } } int main(){ scanf("%d",&n); for(int i=1; i<n; i++){ int x,y; scanf("%d%d",&x,&y); e[x].push_back(y); e[y].push_back(x); } dfs(1,0); f[1]=p;p+=len[1]<<1; g[1]=p;p+=len[1]<<1; DP(1,0); printf("%lld\n",ans); }