在线lca模板

const int N = 4e4 + 1;
int n, step;
int vs[2 * N], dp[2 * N][20], id[N], depth[2 * N];
/*
1.除id以外,其他数组都是2*N;
2.若选择半闭半开 dp时这里分为 [i][j-1] [i+1<<(j-1)][j-1] 加号
3.lca时把区间分为 [L][i-1] [R+1-1<<(i-1)][i-1]    减号
4.lca返回vs[i];
5.初始化有两个;dfs和rmq_dp
*/
struct edge
{
 int to, dis;
 edge(int t, int d) :to(t), dis(d) {};
};
vector<edge>graph[N];
void dfs(int from, int to, int dep, int&step)
{
 id[to] = step;
 vs[step] = to;
 depth[step++] = dep;
 int size = graph[to].size();
 for (int i = 0; i < size; ++i)
  if (graph[to][i].to != from)
  {
   dfs(to, graph[to][i].to, dep + 1, step);
   vs[step] = to;
   depth[step++] = dep;
  }
}
void rmq_dp()
{
 for (int i = 0; i < step; ++i)
  dp[i][0] = i;
 for (int j = 1; 1 << j <= step; ++j)
  for (int i = 0; (i + (1 << j)) <= step; ++i)
  {
   int a = dp[i][j - 1];
   int b = dp[i + (1 << (j - 1))][j - 1];
   dp[i][j] = depth[a] < depth[b] ? a : b;
  }
}
int lca(int L, int R)
{
 L = id[L];
 R = id[R];
 if (L > R)
  swap(L, R);
 int i = 0;
 while (L + 1 << i <= R + 1)
  ++i;
 int a = dp[L][i - 1];//区间为 [   L   ,   L+2*(i-1)  )
 int b = dp[R + 1 - (1 << (i - 1))][i - 1];
 return depth[a] < depth[b] ? vs[a] : vs[b];
}
int main()
{
 step = 0;
 dfs(0, 0, 0, step);
 rmq_dp();//然后就可以用了
}

猜你喜欢

转载自blog.csdn.net/qq_41157212/article/details/80713664