bzoj3376 [Usaco2004 Open]Cube Stacking 方块游戏

Description

约翰和贝茜在玩一个方块游戏.编号为 \(1\)\(n\)\(n(1\leq n\leq 30000)\)个方块正放在地上.每个构成一个立方柱.
游戏开始后,约翰会给贝茜发出\(P(1\leq P\leq 100000)\)个指令.指令有两种:

  1. 移动\((M)\): 将包含 \(X\) 的立方柱移动到包含 \(Y\) 的立方柱上.
  2. 统计\((C)\): 统计名含 \(X\) 的立方柱中,在 \(X\) 下方的方块数目

写个程序帮贝茜完成游戏.

Input

\(1\) 行输入 \(P\),之后 \(P\) 行每行输入一条指令.形式为"M X Y"或者"C X"
输入保证不会有将立方柱放在自己头上的指令.

Output

每一行,对于每个统计指令,输出其结果.

Sample Input

6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4

Sample Output

1
0
2

Solution

带权并查集。记录三个信息,\(fa[x]\)\(dn[x]\)\(dis[x]\),分别表示 \(x\) 所在的柱的最上面的方块、最下面的方块、\(x\) 到最上面方块的距离。

#include<bits/stdc++.h>
using namespace std;

#define N 100001

inline int read() {
    int x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
    while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
}

inline void write(int x) {
    if (!x) { putchar('0'); return; } if (x < 0) putchar('-'), x = -x;
    char buf[30] = ""; int top = 0; while (x) buf[++top] = x % 10 + '0', x /= 10; while (top) putchar(buf[top--]);
}

int fa[N], dn[N], dis[N];

int find(int x) {
    if (fa[x] ^ x) { int y = fa[x]; fa[x] = find(y), dis[x] += dis[y], dn[x] = dn[y]; } return fa[x];
}

int main() {
    int q = read(); rep(i, 1, q) fa[i] = dn[i] = i, dis[i] = 0;
    while (q--) {
        char s[5]; scanf("%s", s);
        if (!(s[0] ^ 'M')) {
            int x = read(), y = read(), fx = find(x), fy = find(y);
            fa[fy] = fx, dis[fy] = dis[dn[fx]] + 1, dn[fx] = dn[fy];
            find(dn[x]), find(dn[y]);
        }
        else { int x = read(); find(x); write(dis[dn[x]] - dis[x]), puts(""); }
    }
    return 0;
}

转载于:https://www.cnblogs.com/aziint/p/8416259.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值