树论

树上 k 级祖先

int lg[n+5],dep[n+5],maxd[n+5],f[n+5][log2(n)+5],son[n+5],top[n+5];
vector<int>up[n+5],down[n+5];
void dfs1(int pos,vector<int>e[]){
  maxd[pos]=dep[pos]=dep[f[pos][0]]+1;
  for(int i=1;i<=lg[dep[pos]]+1;i++)f[pos][i]=f[f[pos][i-1]][i-1];
  for(int i=0;i<e[pos].size();i++){
    if(!dep[e[pos][i]]){
      f[e[pos][i]][0]=pos,dfs1(e[pos][i],e);
      if(maxd[e[pos][i]]>maxd[pos])maxd[pos]=maxd[e[pos][i]],son[pos]=e[pos][i];
    }
  }
}
void dfs2(int pos,vector<int>e[]){
  if(son[pos])top[son[pos]]=top[pos],dfs2(son[pos],e);
  for(int i=0;i<e[pos].size();i++)if(!top[e[pos][i]])top[e[pos][i]]=e[pos][i],dfs2(e[pos][i],e);
  if(top[pos]==pos){
    for(int i=0,t=pos;i<=maxd[pos]-dep[pos];i++)up[pos].push_back(t),t=f[t][0];
    for(int i=0,t=pos;i<=maxd[pos]-dep[pos];i++)down[pos].push_back(t),t=son[t];
  }
}
void init(int n,int s,vector<int>e[]){
  for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
  dfs1(s,e),top[s]=s,dfs2(s,e);
}
int la(int x,int k){
  if(!k)return x;
  x=f[x][lg[k]],k-=(1<<lg[k])+(dep[x]-dep[top[x]]),x=top[x];
  return k>=0?up[x][k]:down[x][-k];
}

笛卡尔树

struct node{
  int ls,rs;
}tr[n+5];
int st[n+5],top;
int build(int n,int a[]){
  for(int i=1,pos;i<=n;i++){
    pos=top;
    while(pos&&a[st[pos]]>a[i])pos--;
    if(pos)tr[st[pos]].rs=i;
    if(pos<top)tr[i].ls=st[pos+1];
    st[++pos]=i,top=pos;
  }
  return st[1];
}

倍增求LCA

int lg[n+5],dep[n+5],f[n+5][log2(n)+5];
void dfs(int pos,int fa,vector<int>e[]){
  f[pos][0]=fa,dep[pos]=dep[fa]+1;
  for(int i=1;i<=lg[dep[pos]]+1;i++)f[pos][i]=f[f[pos][i-1]][i-1];
  for(int i=0;i<e[pos].size();i++)if(e[pos][i]!=fa)dfs(e[pos][i],pos,e);
}
void init(int n,int s,vector<int>e[]){
  for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
  dfs(s,0,e);
}
int lca(int u,int v){
  if(dep[u]<dep[v])swap(u,v);
  while(dep[u]>dep[v])u=f[u][lg[dep[u]-dep[v]]];
  if(u==v)return u;
  for(int i=lg[dep[u]];i>=0;i--)if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
  return f[u][0];
}

树链剖分

int dep[n+5],fa[n+5],sz[n+5],son[n+5],top[n+5],dfn[n+5],cnt;
void dfs1(int pos,vector<int>e[]){
  dep[pos]=dep[fa[pos]]+1,sz[pos]=1;
  for(int i=0;i<e[pos].size();i++){
    if(!dep[e[pos][i]]){
      fa[e[pos][i]]=pos,dfs1(e[pos][i],e),sz[pos]+=sz[e[pos][i]];
      if(sz[e[pos][i]]>sz[son[pos]])son[pos]=e[pos][i];
    }
  }
}
void dfs2(int pos,vector<int>e[]){
  dfn[pos]=++cnt;
  if(son[pos])top[son[pos]]=top[pos],dfs2(son[pos],e);
  for(int i=0;i<e[pos].size();i++)if(!top[e[pos][i]])top[e[pos][i]]=e[pos][i],dfs2(e[pos][i],e);
}
void init(int s,vector<int>e[]){
  dfs1(s,e),fa[s]=top[s]=s,dfs2(s,e);
}
int lca(int u,int v){
  while(top[u]!=top[v]){
    if(dep[top[u]]>dep[top[v]])u=fa[top[u]];
    else v=fa[top[v]];
  }
  return dep[u]<dep[v]?u:v;
}
void add(int u,int v){
  while(top[u]!=top[v]){
    if(dep[top[u]]>dep[top[v]])/*[dfn[top[u]],dfn[u]]*/u=fa[top[u]];
    else /*dfn[top[v]],[dfn[v]]*/v=fa[top[v]];
  }
  if(dep[u]>dep[v])swap(u,v);
  /*[dfn[u],dfn[v]]*/
}

欧拉序求LCA

int vis[n+5],cnt,minn[n*2+5][log2(n*2)+5],lg[n*2+5];
void dfs(int pos,vector<int>e[]){
  minn[vis[pos]=++cnt][0]=pos;
  for(int i=0;i<e[pos].size();i++)if(!vis[e[pos][i]])dfs(e[pos][i],e),minn[++cnt][0]=pos;
}
int cmp(int a,int b){
  return vis[a]<vis[b]?a:b;
}
void init(int s,vector<int>e[]){
  dfs(s,e);
  for(int i=2;i<=cnt;i++)lg[i]=lg[i>>1]+1;
  for(int j=1;1<<j<=cnt;j++)for(int i=1;i+(1<<j)-1<=cnt;i++)minn[i][j]=cmp(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
}
int lca(int u,int v){
  u=vis[u],v=vis[v];
  if(u>v)swap(u,v);
  return cmp(minn[u][lg[v-u+1]],minn[v-(1<<lg[v-u+1])+1][lg[v-u+1]]);
}

DFS 序求 LCA

int dfn[n+5],cnt,minn[n+5][log2(n)+5],lg[n+5];
void dfs(int pos,int fa,vector<int>e[]){
  minn[dfn[pos]=++cnt][0]=fa;
  for(int i=0;i<e[pos].size();i++)if(!dfn[e[pos][i]])dfs(e[pos][i],pos,e);
}
int cmp(int a,int b){
  return dfn[a]<dfn[b]?a:b;
}
void init(int s,vector<int>e[]){
  dfs(s,0,e);
  for(int i=2;i<=cnt;i++)lg[i]=lg[i>>1]+1;
  for(int j=1;1<<j<=cnt;j++)for(int i=1;i+(1<<j)-1<=cnt;i++)minn[i][j]=cmp(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
}
int lca(int u,int v){
  if(u==v)return u;
  u=dfn[u],v=dfn[v];
  if(u>v)swap(u,v);
  return u++,cmp(minn[u][lg[v-u+1]],minn[v-(1<<lg[v-u+1])+1][lg[v-u+1]]);
}

虚树

bool cmp(int a,int b){
  return dfn[a]<dfn[b];
}
void build(){
  top=st[0]=0,sort(a+1,a+k+1,cmp);
  if(!h[1])top=st[1]=1;
  for(int i=1,p,temp;i<=k;i++){
    p=lca(a[i],st[top]);
    while(st[top]!=p){
      temp=st[top--];
      if(dfn[st[top]]<dfn[p])st[++top]=p;
      e[st[top]].push_back(temp),e[temp].push_back(st[top]);
    }
    st[++top]=a[i];
  }
  while(st[top]!=1)e[st[top]].push_back(st[top-1]),e[st[top-1]].push_back(st[top]),top--;
}
posted @ 2024-03-01 09:26  lgh_2009  阅读(7)  评论(0)    收藏  举报