51nod 1830

在这里插入图片描述
路径交有一个结论

所以只需要用线段树合并一下就好了

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define x first
#define y second

using namespace std;

const int N = 5e5 + 10,M = N * 2;

typedef long long ll;
typedef pair<int,int> PII;

int head[N],to[M],last[M],w[M],cnt;
void add(int a,int b,int c){
    
    
    to[++cnt] = b;
    w[cnt] = c;
    last[cnt] = head[a];
    head[a] = cnt;
}

int depth[N],fa[N][22],dis[N];
void dfs(int x,int lastt){
    
    
    fa[x][0] = lastt;
    for(int i = head[x]; i != -1; i = last[i]){
    
    
        int j = to[i];
        if(j == lastt) continue;
        depth[j] = depth[x] + 1;
        dis[j] = dis[x] + w[i];
        dfs(j,x);
    }
}

int lca(int x,int y){
    
    
    if(depth[x] > depth[y]) swap(x,y);
    //depth[x] < depth[y]
    int cha = depth[y] - depth[x];
    for(int i = 20; i >= 0; i--){
    
    
        if((1 << i) <= cha) cha -= 1 << i,y = fa[y][i];
    }
    if(x == y) return x;
    for(int i = 20; i >= 0; i--){
    
    
        int dx = fa[x][i],dy = fa[y][i];
        if(dx != dy) x = dx,y = dy;
    }
    return fa[x][0];
}

bool cmp(int a,int b){
    
    
    return depth[a] > depth[b];
}

PII unite(PII a,PII b){
    
    
    int LCA[5];
    LCA[1] = lca(a.x,b.x);
    LCA[2] = lca(a.x,b.y);
    LCA[3] = lca(a.y,b.x);
    LCA[4] = lca(a.y,b.y);

    sort(LCA + 1,LCA + 5,cmp);

    return {
    
    LCA[1],LCA[2]};
}

PII P[N * 4];
void build(int s,int t,int p){
    
    
    if(s == t){
    
    
        scanf("%d%d",&P[p].x,&P[p].y);
        return;
    }
    int mid = s + t >> 1;
    build(s,mid,p * 2);
    build(mid + 1,t,p * 2 + 1);
    P[p] = unite(P[p * 2],P[p * 2 + 1]);
}

PII query(int s,int t,int p,int l,int r){
    
    
    if(s >= l && t <= r){
    
    
        return P[p];
    }
    int mid = s + t >> 1;
    PII G = {
    
    0,0};
    if(l <= mid) G = query(s,mid,p * 2,l,r);
    if(mid < r){
    
    
        if(G == make_pair(0,0)) G = query(mid + 1,t,p * 2 + 1,l,r);
        else G = unite(G,query(mid + 1,t,p * 2 + 1,l,r));
    }
    return G;
}

int main(){
    
    
    int n;
    cin >> n;
    memset(head,-1,sizeof head);
    for(int i = 1; i <= n - 1; i++){
    
    
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
    }


    dfs(1,0);

    for(int i = 1; i <= 21; i++){
    
    
        for(int x = 1; x <= n; x++)
            fa[x][i] = fa[fa[x][i - 1]][i - 1];
    }

    int m;
    cin >> m;
    build(1,m,1);

    int k;
    cin >> k;
    while(k--){
    
    
        int x,y;
        scanf("%d%d",&x,&y);
        PII G = query(1,m,1,x,y);

        int t = lca(G.x,G.y);

        cout << dis[G.x] + dis[G.y] - 2 * dis[t] << endl;
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qqqingyi/article/details/120063515
今日推荐