区间节点的lca

题目hdu5266

分析:多节点的LCA就是dfs序中最大最小两个节点的LCA。所以只要每次维持给出节点的dfs序的最大最小,然后就是两点的LCA

代码:

rmq的st+lca的倍增

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
//#include<bits/stdc++.h>
using namespace std;
const int max_=311111;
int n;
int edge[max_*2];
bool vis[max_];
int deep[max_];
int p[max_][25];
int dp_min[max_][25];
int dp_max[max_][25];
int a[max_];
//int smax[max_][25],smin[max_][23];
int tot,idx;
void init()
{
    tot=0;
    memset(edge,-1,sizeof(edge));
    idx=0;
    memset(vis,0,sizeof(vis));
    memset(deep,0,sizeof(deep));
    memset(p,-1,sizeof(p));
}
struct tree{
    int to;
    int next;
}G[max_*2];

void add_edge(int u,int v)
{
    G[++tot].to=v;
    G[tot].next=edge[u];
    edge[u]=tot;
}
void dfs(int u)
{
    vis[u]=1;
    a[u-1]=idx++;
    for(int i=edge[u];~i;i=G[i].next)
    {
        int v=G[i].to;
        if(!vis[v])
        {
            p[v][0]=u;
            deep[v]=deep[u]+1;
            dfs(v);
        }
    }
}
int Max(int x,int y)
{
    if(a[x]>a[y])
        return x;
    else
        return y;
}
int Min(int x,int y)
{
    if(a[x]>a[y])
        return y;
    else
        return x;
}
void st_init()
{
    for(int i=0;i<n;i++)
    {
        dp_max[i][0]=i,
        dp_min[i][0]=i;
    }
    for(int j=1;(1<<j)<=n;j++)
        for(int i=0;i+(1<<j)-1<n;i++)
    {
        dp_max[i][j]=Max(dp_max[i][j-1],dp_max[i+(1<<(j-1))][j-1]);
        dp_min[i][j]=Min(dp_min[i][j-1],dp_min[i+(1<<(j-1))][j-1]);
    }
}
int st_q_max(int l,int r)
{
    int k=0;
    while((1<<(k+1))<=r-l+1)
        k++;
    return Max(dp_max[l][k],dp_max[r-(1<<k)+1][k]);
}
int st_q_min(int l,int r)
{
    int k=0;
    while((1<<(k+1))<=r-l+1)
        k++;
    return Min(dp_min[l][k],dp_min[r-(1<<k)+1][k]);
}
void lca_init()
{
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i<=n;i++)
        if(~p[i][j-1])
        p[i][j]=p[p[i][j-1]][j-1];
}
int lca(int u,int v)
{
   if(deep[u]<deep[v])//u_max;
        swap(u,v);
   int k=deep[u]-deep[v];
   for(int i=0;(1<<i)<=k;i++)
   {
       if((1<<i)&k)
        u=p[u][i];
   }
   if(u==v)
    return u;
    int N=log2((double)n);
   for(int i=N;i>=0;i--)
   {
       if(p[u][i]!=p[v][i])
       {
           u=p[u][i],
           v=p[v][i];
       }
   }
   return p[u][0];
}
int main()
{
    while(~scanf("%d",&n)){
       init();
      int u,v;
   for(int i=1;i<n;i++)
   {
      scanf("%d %d",&u,&v);
      add_edge(u,v);
      add_edge(v,u);
   }
   dfs(1);
   st_init();
   int Q;
   scanf("%d",&Q);
   lca_init();
   while(Q--)
   {
       int l,r;
       scanf("%d %d",&l,&r);
       l--,r--;
       int id_max=st_q_max(l,r)+1;
       int id_min=st_q_min(l,r)+1;
       printf("%d\n",lca(id_max,id_min));
   }
  }
}
View Code

猜你喜欢

转载自www.cnblogs.com/linhaitai/p/10035452.html
lca
今日推荐