• hdu 2818 Building Block(加权并查集)2009 Multi-University Training Contest 1


    题意:

    一共有30000个箱子,刚开始时都是分开放置的。接下来会有两种操作:

    1. M x y,表示把x箱子所在的一摞放到y箱子那一摞上。

    2. C y,表示询问y下方有多少个箱子。

    输入:

    首行输入一个整数m,表示一共有m次操作。

    接下来每次操作都是上面所说的两种中的一种。

    输出:

    每次C y,输出一个结果,每次输出占1行。

    就是不知道究竟是只有一组测试样例还是有多组测试样例,不过我还是按照多组的方式写了。

    题解:

    这道题我自己思考了好久都没有思路,最后中忍不住去看了题解,然后被题解震惊了。

    明明只有1个权值,题解中的方式愣是把这一个权拆成了两部分,然后算出结果,Orz。

    两个权是tot[], sum[],tot[i]表示i所在的箱子堆中一共有tot[i]个箱子,其中只有根节点的tot[i]是必须的。sum[i]则表示i下方共有sum[i]个箱子。

    接下来,每次合并时,都将被合并的根节点fx的sum[]值加上仍然存在的根节点fy的tot[]值,然后fy的tot[]则加上fx的tot[]。

    即,sum[fx] += tot[fy]; tot[fy] += tot[fx];

    接下来,每次查找时,都要讲节点x的sum[]加上x的父节点的sum[]。

    即,sum[x] += sum[fm[x]];

    具体见代码——

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int N = 30010;
     8 
     9 int fm[N], sum[N], tot[N];
    10 int n;
    11 int a, b;
    12 char s[2];
    13 
    14 void init()
    15 {
    16     for(int i = 0; i < N; i++)          //很坑爹,题目明明说是1~30000,但是必须将0也初始化才能过
    17     {
    18         fm[i] = i;
    19         sum[i] = 0;
    20         tot[i] = 1;
    21     }
    22 }
    23 
    24 int mfind(int x)
    25 {
    26     if(x == fm[x]) return x;
    27     int t = fm[x];
    28     fm[x] = mfind(fm[x]);
    29     sum[x] += sum[t];
    30     return fm[x];
    31 }
    32 
    33 void mmerge()
    34 {
    35     int fx = mfind(a);
    36     int fy = mfind(b);
    37     if(fx != fy)
    38     {
    39         fm[fx] = fy;
    40         sum[fx] += tot[fy];
    41         tot[fy] += tot[fx];
    42     }
    43 }
    44 
    45 void work()
    46 {
    47     for(int tm = 1; tm <= n; tm++)
    48     {
    49         scanf("%s", s);
    50         if(s[0] == 'M')
    51         {
    52             scanf("%d%d", &a, &b);
    53             mmerge();
    54         }
    55         else
    56         {
    57             scanf("%d", &a);
    58             mfind(a);
    59             printf("%d
    ", sum[a]);
    60         }
    61     }
    62 }
    63 
    64 int main()
    65 {
    66     //freopen("test.in", "r", stdin);
    67     while(~scanf("%d", &n))
    68     {
    69         init();
    70         work();
    71     }
    72     return 0;
    73 }
    View Code
  • 相关阅读:
    10.2 处理大集合
    观察者模式——出版者与订阅者
    phonegap(cordova) 自己定义插件代码篇(五)----android ,iOS 集成微信登陆
    另一鲜为人知的单例写法-ThreadLocal
    Spring MVC中Controller如何将数据返回给页面
    IntelliJ IDEA安装主题详细步骤
    oracle导出dmp文件的2种方法
    Oracle导出表(即DMP文件)的两种方法
    Spring MVC 实现文件的上传和下载
    压力测试 JMeter3.3
  • 原文地址:https://www.cnblogs.com/mypride/p/4750684.html
Copyright © 2020-2023  润新知