【35.12%】【POJ 1988】Cube Stacking

Time Limit: 2000MS Memory Limit: 30000K
Total Submissions: 24007 Accepted: 8432
Case Time Limit: 1000MS
Description

Farmer John and Betsy are playing a game with N (1 <= N <= 30,000)identical cubes labeled 1 through N. They start with N stacks, each containing a single cube. Farmer John asks Betsy to perform P (1<= P <= 100,000) operation. There are two types of operations:
moves and counts.
* In a move operation, Farmer John asks Bessie to move the stack containing cube X on top of the stack containing cube Y.
* In a count operation, Farmer John asks Bessie to count the number of cubes on the stack with cube X that are under the cube X and report that value.

Write a program that can verify the results of the game.
Input

  • Line 1: A single integer, P

  • Lines 2..P+1: Each of these lines describes a legal operation. Line 2 describes the first operation, etc. Each line begins with a ‘M’ for a move operation or a ‘C’ for a count operation. For move operations, the line also contains two integers: X and Y.For count operations, the line also contains a single integer: X.

Note that the value for N does not appear in the input file. No move operation will request a move a stack onto itself.
Output

Print the output from each of the count operations in the same order as the input file.
Sample Input

6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4
Sample Output

1
0
2
Source

USACO 2004 U S Open

【题解】

题目的意思:
给你n个有标号的木块。
一开始全部摆放在地面上。
然后M 1 6的话,就是把地面上的标号1木块叠在6木块上面.
1
6 2 3 4 5
这时1下面有一个木块6所以C1==1;
再M 2 4,即把2号木块叠在4号木块上面
1 2
6 3 4 5
然后M 2 6即把2号木块所在的堆整个放在1号木块所在的堆
2
4
1
6 3 5
这样4号下面就只有两个木块;
做法:
带权并查集。
父亲指向底端的木块。
re[x]表示当前这个木块下面有多少个木块;
cnt[x]表示x个节点下面包括自己有多少个木块;
用带权向量(我也不知道有没有这个名词,但是听起来挺厉害的。)转移的时候。就不用那么麻烦了;
假设x和y的根节点分别为a,b;
则f[a]=b;
表示把a放在b所在堆的上面;
则a下面需要增加的代价就是cnt[b];
加上去就好了
至于a的上面的元素。会在ff函数里面进行路径压缩的时候累加上去;
所以不用担心。
和银河英雄传说那题很像。
还是安利下带权并查集的通解
http://blog.csdn.net/harlow_cheng/article/details/52737486

#include <cstdio>
#include <iostream>

using namespace std;

const int MAXN = 30000;

int f[MAXN+100], re[MAXN+100],cnt[MAXN+100];

void input(int &r)
{
    r = 0;
    char t = getchar();
    while (!isdigit(t)) t = getchar();
    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
}

int ff(int x)
{
    if (f[x] == x)
        return x;
    int olfa = f[x];
    f[x] = ff(f[x]);
    re[x] = re[x] + re[olfa];
    return f[x];
}

int main()
{
    //freopen("F:\rush.txt", "r", stdin);
    for (int i = 1; i <= MAXN; i++)
        f[i] = i, re[i] = 0,cnt[i] =1;
    int p;
    input(p);
    for (int i = 1; i <= p; i++)
    {
        char key[5];
        scanf("%s", key);
        if (key[0] == 'M')
        {
            int x, y;
            input(x); input(y);
            int a = ff(x), b = ff(y);
            if (a != b)
            {
                f[a] = b;
                re[a] = re[a]+cnt[b];
                cnt[b] += cnt[a];
            }
        }
        else
        {
            int x;
            input(x);
            ff(x);
            printf("%d
", re[x]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7632174.html