• 【边带权 维护节点和根距离 两点距离】银河英雄传说


    传送门

    题意

    初始有(N)艘战舰,开始每个战舰单独一列,有(t)条指令,每个指令可能包含两个操作

    1. ((M , i , j)),表示让第(i)号战舰所在列的全部战舰保持原有顺序,接在第(j)号战舰所在列的尾部。
    2. ((C , i , j)),表示询问第(i)号战舰与第(j)号战舰当前是否处于同一列中,如果在同一列中,它们之间间隔了多少艘战舰。

    数据范围

    (1 leq N leq 3 imes 10^{4})
    (1 leq t leq 5 imes 10^{5})

    题解

    • 维护当前的集合的大小(sz)(d)表示当前点到树根的距离

      • 到根的距离需要在查询时维护如果到根的距离,当前节点到根部的距离未被更新过时,就累加原祖先到根部的距离
    • 求得是两点之间的间隔,间隔即两个点中间有几个点,中间的点不包括这条路径的起点和终点

      • 每次询问间隔时候两个到根距离的差的绝对值(-1)就是间隔了多少个

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for(int i=a;i<n;i++)
    #define per(i,a,n) for(int i=n-1;i>=a;i--)
    
    const int N=3e5+10;
    int fa[N],sz[N],d[N];
    
    
    int _;
    int find(int x)
    {
        if(fa[x]==x) return x;
        int root=find(fa[x]);
        d[x]+=d[fa[x]];
        return fa[x]=root;
    }
    void merge(int a,int b)
    {
        int pa=find(a),pb=find(b);
        d[pa]=sz[pb];
        sz[pb]+=sz[pa];
        fa[pa]=pb;
    }
    void solve()
    {
        char op[2];
        int x,y;
        cin>>op>>x>>y;
        if(op[0]=='M') merge(x,y);
        else 
        {
            int pa=find(x),pb=find(y);
            if(pa==pb)
                cout<<abs(d[x]-d[y])-1<<endl;
            else
                cout<<"-1"<<endl;
        }
    }
    int main()
    {
        cin>>_;
        rep(i,1,N) fa[i]=i,sz[i]=1,d[i]=0;
        while(_--) solve();
    }
    
  • 相关阅读:
    批处理系列(10)
    批处理系列(11)
    批处理系列(9)
    批处理系列(7)
    批处理系列(8)
    批处理系列(6)
    批处理系列(4)
    批处理系列(5)
    Java项目性能监控和调优工具-Javamelody的学习总结
    easyUI 接收Spring Mvc中@ResponseBody中文乱码解决
  • 原文地址:https://www.cnblogs.com/hhyx/p/13433348.html
Copyright © 2020-2023  润新知