树剖求LCA模板

  •  O(logn)(n<=10^6)
  • https://www.cnblogs.com/cangT-Tlan/p/8846408.html
  • 把一棵树分成几条链,用数据结构去维护每一条链
  • 复制代码
     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define rll register ll
     4 #define M 0x3f3f3f
     5 #define For(i,l,r) for(int i=l;i<=r;i++)
     6 using namespace std; 
     7 ll n,m,s,head[M],a[M],x,y,z,tot,k,t;
     8 ll fa[M],d[M],top[M],size[M],id[M],ril[M];
     9 struct node1{
    10     ll to,nxt;
    11 }e[M<<1];
    12 struct node2{
    13     ll l,r,sum,flag;
    14 }tree[M<<1];
    15 
    16 inline ll read(){
    17     ll f=1,sum=0;
    18     char ch=getchar();
    19     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    20     while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
    21     return f*sum;
    22 }
    23 
    24 inline void add(ll x,ll y){
    25     e[++tot].to=y;
    26     e[tot].nxt=head[x];
    27     head[x]=tot;
    28 }
    29 
    30 inline void dfs1(ll u){//第一遍dfs遍历树,预处理d深度,size此点子节点个数,fa其父节点
    31     d[u]=d[fa[u]]+1;
    32     size[u]=1;
    33     for(rll i=head[u];i;i=e[i].nxt){
    34         if(e[i].to!=fa[u]){
    35             fa[e[i].to]=u;
    36             dfs1(e[i].to);
    37             size[u]+=size[e[i].to];
    38         }
    39     }
    40 }
    41 
    42 inline void dfs2(ll u){//按照子节点个数多少划分轻重边,保证一个点只在一条链中。一般只用重边,轻边用不到。
    43     ll t=0;//top即为此点所在重边的顶点 
    44     if(!top[u]) top[u]=u;
    45     for(rll i=head[u];i;i=e[i].nxt){
    46         if(e[i].to!=fa[u]&&size[e[i].to]>t) t=e[i].to;
    47     }
    48     if(t){
    49         top[t]=top[u];
    50         dfs2(t);
    51     }
    52     for(rll i=head[u];i;i=e[i].nxt){
    53         if(e[i].to!=fa[u]&&e[i].to!=t) dfs2(e[i].to); 
    54     }
    55 }
    56 
    57 inline ll lca(ll x,ll y){//当两个点位于同一条重链上即结束操作。否则深度深的点跳到所在重链的上一个点,结束操作时深度浅的点的位置即为所求lca
    58     while(top[x]!=top[y]){
    59         if(d[top[x]]<d[top[y]]) swap(x,y);
    60         x=fa[top[x]];
    61     }
    62     if(d[x]>d[y]) swap(x,y);
    63     return x;
    64 }
    65 
    66 int main(){
    67     n=read(),m=read(),s=read();
    68     For(i,1,n-1) {x=read(),y=read(),add(x,y),add(y,x);}
    69     dfs1(s),dfs2(s);
    70     For(i,1,m){x=read(),y=read(),printf("%lld\n",lca(x,y));}
    71     return 0;
    72 }
    复制代码

     

posted @   song_jian  阅读(128)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示