poj1988
题意:有n个元素,开始每个元素自己一栈,有两种操作,将含有元素x的栈放在含有y的栈的顶端,合并为一个栈。第二种操作是询问含有x元素下面有多少个元素。
分析:并查集,因为当我们知道栈中元素的总数,和某元素到栈顶的距离,我们就能知道这个元素下面有多少元素。我们并操作的时候,始终使用在上面栈的代表元来做合并之后的代表元,这样也就达到了栈中的代表元是栈中的堆顶元素的效果,我们只需在每个代表元中记录该栈中的元素总数即可。然而我们还需要得知某元素到代表元的距离,这样我们就需要记录每个元素到其父亲的距离,把它到代表元上所经过的距离加起来,即为它到代表元的距离。这样我们就得出了结果。另外优化的过程(把路上所有元素的father改为代表元的过程)比较复杂,容易错。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
usingnamespace std;
#define maxn 30003
struct Block
{
int father, tot, dis;
}block[maxn];
int n;
void init()
{
for (int i =0; i < maxn; i++)
{
block[i].father = i;
block[i].tot =1;
block[i].dis =0;
}
}
int getanc(int a)
{
int ret;
if (block[a].father == a)
return a;
ret = getanc(block[a].father);
block[a].dis += block[block[a].father].dis;
block[a].father = ret;
return ret;
}
void move()
{
int a, b;
scanf("%d%d", &a, &b);
int anc1 = getanc(a);
int anc2 = getanc(b);
block[anc2].dis = block[anc1].tot;
block[anc2].father = anc1;
block[anc1].tot = block[anc1].tot + block[anc2].tot;
}
void count()
{
int a;
scanf("%d", &a);
int anc = getanc(a);
printf("%d\n", block[anc].tot - block[a].dis -1);
}
int main()
{
//freopen("D:\\t.txt", "r", stdin);
scanf("%d", &n);
init();
for (int i =0; i < n; i++)
{
char st[3];
scanf("%s", st);
if (strcmp(st, "M") ==0)
move();
else
count();
}
return0;
}
#include <cstdlib>
#include <cstring>
#include <cstdio>
usingnamespace std;
#define maxn 30003
struct Block
{
int father, tot, dis;
}block[maxn];
int n;
void init()
{
for (int i =0; i < maxn; i++)
{
block[i].father = i;
block[i].tot =1;
block[i].dis =0;
}
}
int getanc(int a)
{
int ret;
if (block[a].father == a)
return a;
ret = getanc(block[a].father);
block[a].dis += block[block[a].father].dis;
block[a].father = ret;
return ret;
}
void move()
{
int a, b;
scanf("%d%d", &a, &b);
int anc1 = getanc(a);
int anc2 = getanc(b);
block[anc2].dis = block[anc1].tot;
block[anc2].father = anc1;
block[anc1].tot = block[anc1].tot + block[anc2].tot;
}
void count()
{
int a;
scanf("%d", &a);
int anc = getanc(a);
printf("%d\n", block[anc].tot - block[a].dis -1);
}
int main()
{
//freopen("D:\\t.txt", "r", stdin);
scanf("%d", &n);
init();
for (int i =0; i < n; i++)
{
char st[3];
scanf("%s", st);
if (strcmp(st, "M") ==0)
move();
else
count();
}
return0;
}