st表求lca

对于st表求lca可以做到O(1)查询。

对于一个欧拉序,每个点对应其第一次出现在欧拉序中的位置。

然后查询区间dep的最小值,这是st表干的。

完了。

void dfs(int u,int faa){
		dep[u]=dep[faa]+1;fa[u][0]=faa;dfn[u]=++cntdfn;
		fir[u]=++cntt;st[0][cntt]=u;
		for(int i=1;i<=18;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
		for(int i=first[u];i;i=nxt[i]){
			int v=to[i];if(v==faa)continue;
			dfs(v,u);st[0][++cntt]=u;
		}
	}
	void prepare(){
		lg[0]=-1;for(int i=1;i<=N*2;i++)lg[i]=lg[i>>1]+1;
		for(int i=1;i<=17;i++){
			for(int j=1;j+(1<<i)-1<=cntt;j++){
				st[i][j]=dep[st[i-1][j]]<dep[st[i-1][j+(1<<(i-1))]]?st[i-1][j]:st[i-1][j+(1<<(i-1))];
			}
		}
	}
	int Lca(int a,int b){
		int l=fir[a],r=fir[b],k;
		if(l>r)swap(l,r);
		k=lg[r-l+1];
		return dep[st[k][l]]<dep[st[k][r-(1<<k)+1]]?st[k][l]:st[k][r-(1<<k)+1];
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值