原题链接:https://www.luogu.com.cn/problem/P5092
Cube Stacking
题目描述
约翰和贝茜在玩一个方块游戏。编号为 1 … n 1\ldots n 1…n 的 n n n ( 1 ≤ n ≤ 30000 1 \leq n \leq 30000 1≤n≤30000 )个方块正放在地上,每个构成一个立方柱。
游戏开始后,约翰会给贝茜发出 P P P ( 1 ≤ P ≤ 100000 1 \leq P \leq 100000 1≤P≤100000 )个指令。指令有两种:
移动(M):将包含 X 的立方柱移动到包含 Y 的立方柱上。
统计(C):统计含 X 的立方柱中,在 X 下方的方块数目。
写个程序帮贝茜完成游戏。
输入格式
第1行输入 P P P ,之后 P P P 行每行输入一条指令,形式为 M X Y
或者 C X
。
输入保证不会有将立方柱放在自己头上的指令。
输出格式
输出共 P P P 行,对于每个统计指令,输出其结果。
输入输出样例
输入 #1
6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4
输出 #1
1
0
2
题解
没想到USACO2004居然会抄NOI2002,还做了简化……
直接把NOI2002照搬过来就好了。
不过我在改 a s k ask ask函数的时候把更新的操作(即 r o o t ( a ) root(a) root(a))这一步改掉了,还 W A \mathcal{WA} WA了一下,退役老咸鱼泪目。
代码
import sys
sys.setrecursionlimit(30005)
n=30000
dad=[0 for i in range(1,5+n)]
siz=[1 for i in range(1,5+n)]
dis=[0 for i in range(1,5+n)]
def root(v):
if(dad[v]==v):
return v
dv=dad[v]
dad[v]=root(dad[v])
dis[v]+=dis[dv]
siz[v]=siz[dv]
return dad[v]
def link(a,b):
ra=root(a)
rb=root(b)
dad[ra]=rb
dis[ra]+=siz[rb]
siz[ra]+=siz[rb]
siz[rb]=siz[ra]
def ask(a):
root(a)
print(dis[a])
def ac():
T=int(input())
for i in range(1,T+1):
order=input().split()
a=int(order[1])
if order[0]=='M':
link(a,int(order[2]))
else:
ask(a)
return
for i in range(0,n+1):
dad[i]=i
ac()
#include<bits/stdc++.h>
using namespace std;
const int M=3e4+5;
int T;
int dad[M],dis[M],siz[M];
char order[2];
int root(int v)
{
if(v==dad[v])return v;
int dv=dad[v];
dad[v]=root(dad[v]);
dis[v]+=dis[dv];
siz[v]=siz[dad[v]];
return dad[v];
}
void link(int a,int b)
{
int ra=root(a),rb=root(b);
dad[ra]=rb,dis[ra]+=siz[rb],siz[ra]+=siz[rb];
siz[rb]=siz[ra];
}
void ask(int a)
{
root(a);
printf("%d\n",dis[a]);
}
void in(){
scanf("%d",&T);}
void ac()
{
for(int i=3e4;i>=1;--i)dad[i]=i,siz[i]=1;
int a,b;
for(int i=1;i<=T;++i)
{
scanf("%s%d",order,&a);
if(order[0]=='M')scanf("%d",&b),link(a,b);
else ask(a);
}
}
int main()
{
in(),ac();
system("pause");
}