倍增和树上倍增
倍增表又称ST表,是一种离线算法,不支持修改,在离线算法中,复杂度非常快,代码简洁实用
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include<bits/stdc++.h> #define ll long long using namespace std; const int N = (1<<13)+39+7; int n,m,l,r,st[N][N],LOG2[N]; int main(){ cin>>n>>m; for ( int i=1;i<=n;i++)cin>>st[i][0]; for ( int i=2;i<=n;i++)LOG2[i]=LOG2[i>>1]+1; for ( int i=1;i<13;i++){ for ( int j=1;j+(1<<i)-1<=n;j++){ st[j][i]=max(st[j][i-1],st[j+(1<<i)-1][i-1]); } } while (m--){ cin>>l>>r; int Log2=LOG2[r-l+1]; cout<<max(st[l][Log2],st[r-(1<<Log2)+1][Log2])<< '\n' ; } return 0; } |
现在,将线性的倍增变成树形的倍增,其中最常见的应用就是最近公共祖先(LCA),求解LCA的思路有很多,比如说树链剖分,tarjan等
下面给出一道例题
解析:
最近公共祖先(LCA)模板
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #include<bits/stdc++.h> #define ll long long using namespace std; const int N = 5e5+39+7; int n,m,s,fa[N][20],dep[N]; vector< int >G[N]; void dfs( int x, int father){ fa[x][0]=father; dep[x]=dep[father]+1; for ( auto y:G[x]){ if (y==father) continue ; dfs(y,x); } } void init(){ for ( int i=1;i<20;i++){ for ( int x=1;x<=n;x++){ fa[x][i]=fa[fa[x][i-1]][i-1]; } } } int lca( int x, int y){ if (dep[x]<dep[y])swap(x,y); for ( int i=19;i>=0;i--) if (dep[x]-dep[y]>=(1<<i))x=fa[x][i]; if (x==y) return x; for ( int i=19;i>=0;i--) if (fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i]; return fa[x][0]; } int main(){ cin>>n>>m>>s; for ( int i=1;i<n;i++){ int x,y; cin>>x>>y; G[x].push_back(y); G[y].push_back(x); } dfs(s,0); init(); while (m--){ int x,y;cin>>x>>y; cout<<lca(x,y)<< '\n' ; } return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现