LCA(在线)

#include"iostream"
#include"cstring"
using namespace std;
const int maxn=4e4+5;
int N,Q;
int dp[maxn<<1][20];//保存cnt节点区间里深度最小的节点
struct Edge
{
    int t,next,v;
};
Edge E[maxn<<1];
int head[maxn],tot;
int dep[maxn<<1];
int First[maxn];//第cnt个节点是哪个点
int cnt;//遍历的第cnt个节点
int id[maxn<<1];//第cnt个节点是原来树上的第几个
void AddEdge(int aa,int bb,int v)
{
    E[++tot].t=bb;
    E[tot].v=v;
    E[tot].next=head[aa];
    head[aa]=tot;
}
void dfs(int u,int pre,int deep)
{
    id[++cnt]=u;
    First[u]=cnt;
    dep[cnt]=deep;
    dp[cnt][0]=cnt;
    for(int i=head[u];i!=-1;i=E[i].next)
    {
        int t=E[i].t;
        int v=E[i].v;
        if(t==pre)continue;
        dfs(t,u,deep+v);
        id[++cnt]=u;
        dep[cnt]=deep;
        dp[cnt][0]=cnt;
    }
}
void RMQ_ST()
{
    for(int j=1;(1<<j)<=cnt;j++)
    {
        for(int i=1;i+(1<<j)-1<=cnt;i++)
        {
            int cnt1=dp[i][j-1],cnt2=dp[i+(1<<(j-1))][j-1];
            if(dep[cnt1]<dep[cnt2])dp[i][j]=cnt1;
            else dp[i][j]=cnt2;
        }
    }
}
int query(int L,int R)
{
    L=First[L];
    R=First[R];
    if(L>R)swap(L,R);
    int k=0;
    while(1<<(k+1)<(R-L+1))k++;
    int cnt1=dp[L][k],cnt2=dp[R-(1<<k)+1][k];
    if(dep[cnt1]<dep[cnt2])return id[cnt1];
    else return id[cnt2];
}
void printid(int L,int R)
{
    for(int i=L;i<=R;i++)cout<<id[i]<<" ";
    cout<<"\n";
    for(int i=L;i<=R;i++)cout<<dep[i]<<" ";
    cout<<"\n\n";
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>N>>Q;
        tot=0;
        cnt=0;
        memset(head,-1,sizeof(head));
        for(int i=1;i<N;i++)
        {
            int t1,t2,v;
            cin>>t1>>t2>>v;
            AddEdge(t1,t2,v);
            AddEdge(t2,t1,v);
        }
        int root=1;
        dfs(root,-1,0);
        RMQ_ST();
        for(int i=1;i<=Q;i++)
        {
            int u1,u2;
            cin>>u1>>u2;
            int u=query(u1,u2);
            cout<<dep[First[u1]]+dep[First[u2]]-2*dep[First[u]]<<endl;
        }
    }
}