洛谷P1196 银河英雄传说

大意:你有30000个队列,第i个队列中只有i

有T个操作,1,把某个队列头接到另一个队列尾。

2,问两个元素之间的距离。

本题主要有三种解法。

①带权并查集。

具体来说就是,并查集维护当前集合的大小,这个点距离代表元(队首)的边数。

然后把合并和路径压缩魔改一下。询问的时候就直接取距离之差。

 1 #include <cstdio>
 2 
 3 const int N = 30010;
 4 
 5 int fa[N], sum[N], siz[N];
 6 char str[5];
 7 
 8 inline int find(int x, int &s) {
 9     if(fa[x] == x) {
10         s = 0;
11         return x;
12     }
13     int t = find(fa[x], s);
14     s += sum[x];
15     sum[x] = s;
16     return fa[x] = t;
17 }
18 
19 inline void merge(int x, int y) {
20     int a, b;
21     x = find(x, a);
22     y = find(y, b);
23     fa[x] = y;
24     sum[x] = siz[y];
25     siz[y] += siz[x];
26     return;
27 }
28 
29 inline int ask(int x, int y) {
30     int a, b;
31     x = find(x, a);
32     y = find(y, b);
33     if(x != y) {
34         return -1;
35     }
36     return (a > b ? a - b : b - a) - 1;
37 }
38 
39 int main() {
40     int n;
41     scanf("%d", &n);
42     for(int i = 1; i <= 30000; i++) {
43         fa[i] = i;
44         siz[i] = 1;
45     }
46     for(int i = 1, x, y; i <= n; i++) {
47         scanf("%s%d%d", str, &x, &y);
48         if(str[0] == 'M') {
49             merge(x, y);
50         }
51         else {
52             printf("%d\n", ask(x, y));
53         }
54     }
55 
56     return 0;
57 }
AC代码

②平衡树

这个太暴力了......开30000颗平衡树即可。

③离线(kruskal重构树)

重构的时候把顺序搞一下,然后提出来DFS序,直接回答询问。

 

posted @ 2018-11-24 20:44  huyufeifei  阅读(155)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

ReadEra 阅读书籍

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜