经典并查集
看的时候思路还卡了一下
这题唯一的问题就在于需要维护一排中最后一个的位置
其实维护一下总个数就行了
sze记录总个数 dis记录与根节点的距离
所以合并方程比较显然
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #define By prophetB 6 #define rep(i,a,n) for(int i = a;i <= n;i++) 7 #define per(i,n,a) for(int i = n;i >= a;i--) 8 #define inf 2147483647 9 #define ms(a,b) memset(a,b,sizeof a) 10 using namespace std; 11 typedef long long ll; 12 ll read() { 13 ll as = 0,fu = 1; 14 char c = getchar(); 15 while(c < '0' || c > '9') { 16 if(c == '-') fu = -1; 17 c = getchar(); 18 } 19 while(c >= '0' && c <= '9') { 20 as = as * 10 + c - '0'; 21 c = getchar(); 22 } 23 return as * fu; 24 } 25 const int N = 30005; 26 //head 27 int pa[N],sze[N],dis[N]; 28 int gpa(int x) { 29 if(pa[x] == x) return x; 30 int t = pa[x]; 31 pa[x] = gpa(t); 32 sze[x] = sze[pa[x]]; 33 dis[x] += dis[t]; 34 return pa[x]; 35 } 36 37 void Merge(int x,int y) { 38 int fx = gpa(x); 39 int fy = gpa(y); 40 if(fx == fy) return; 41 pa[fx] = fy; 42 dis[fx] = dis[fy] + sze[fy]; 43 sze[fx] = sze[fy] = (sze[fx] + sze[fy]); 44 return; 45 } 46 47 int query(int x,int y) { 48 int fx = gpa(x); 49 int fy = gpa(y); 50 if(fx == fy) return abs(dis[y] - dis[x]) - 1; 51 else return -1; 52 } 53 54 int main() { 55 rep(i,1,30000) pa[i] = i,sze[i] = 1; 56 int T = read(); 57 char s[5]; 58 while(T--) { 59 scanf("%s",s); 60 if(s[0] == 'M') { 61 int x = read(); 62 int y = read(); 63 Merge(x,y); 64 } else { 65 int x = read(); 66 int y = read(); 67 printf("%d ",query(x,y)); 68 } 69 } 70 return 0; 71 }
这里sze我让每个节点都返回整个的sze 方便一点