D34【模板】长链剖分 CF1009F Dominant Indices

视频链接:333 长链剖分【模板】CF1009F Dominant Indices_哔哩哔哩_bilibili

 

 

 

 

 

CF1009F Dominant Indices

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);
}
View Code
复制代码

Luogu P4292 [WC2010] 重建计划

Luogu P3899 [湖南集训] 更为厉害

攻略 - BZOJ by HydroOJ

Luogu P5903 【模板】树上 k 级祖先

 

posted @   董晓  阅读(408)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示