题目
思路
我们单独考虑如果将包含\(x\)的立方柱移动包含\(y\)的立方柱上会有什么影响
首先对于原来的包含\(y\)的立方柱,所有的答案都不会发生任何变化
对于包含\(x\)的立方柱,他们所有的答案都会加上包含\(y\)的立方柱的大小
简单的去考虑,这道题可以用平衡树去做
毕竟操作只有求值,平衡树的合并,区间加法
时间复杂度为\(O(nlog_n)\)
本篇博客主要介绍带权冰茶姬的做法
其实也差不多,
因为每一次的操作都是针对整个冰茶姬进行操作
所以我们所有的操作都可以直接打到根上,
在\(findset\)操作的时候用父亲节点的信息进行维护
至于\(size\)的维护更简单
只有在合并两个冰茶姬的时候维护一下就可以了
代码
#include<iostream>
using namespace std;
int n;
int fa[30005];
int siz[30005];
int ans[30005];
char opt;
inline void makeset(int n)
{
for(int i=1;i<=30000;i++)
{
fa[i]=i;
siz[i]=1;
ans[i]=0;
}
}
inline int findset(int u)
{
if(fa[u]==u)
return u;
int t=fa[u];
fa[u]=findset(fa[u]);
ans[u]+=ans[t];
return fa[u];
}
inline void unionset(int a,int b)
{
int u=findset(a);
int v=findset(b);
if(u==v)
return;
fa[v]=u;
ans[v]+=siz[u];
siz[u]+=siz[v];
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
makeset(n);
for(int i=1,u,v;i<=n;i++)
{
cin>>opt;
if(opt=='M')
{
cin>>u>>v;
unionset(v,u);
}
else
{
cin>>u;
findset(u);
cout<<ans[u]<<endl;
}
}
return 0;
}