传送门 cube stacking
给定一堆立方体,每次move都将此方块所在的整堆都移动道另外一堆上面
每次querry 输出编号下面有多少个立方体
思路并查集并且保留深度
/*
刚开始没有用一个deep数组记录深度,而是直接递归寻找深度,时间爆了
诶........
*/
#include <stdio.h>
#include <iostream>
using namespace std ;
const int maxn = 1e5+5 ;
int ufs[maxn] ;
int num[maxn] , deep[maxn] ;
int p ;
void init ( )
{
for( int i = 1 ; i <= maxn ; i++ ) ufs[i] = i , num[i] = 1 , deep[i] = 0 ;
}
int find_set( int x )
{
if( x == ufs[x] ) return x ;
int tmp = ufs[x] ;
ufs[x] = find_set(ufs[x] ) ;
deep[x] += deep[tmp] ; // 求深度
return ufs[x] ;
}
void union_set( int a , int b )
{
a = find_set(a) ;
b = find_set(b) ;
if( a == b ) return ;
ufs[b] = a ;
deep[b] = num[a] ;
num[a] += num[b] ;
}
/*
int find_ans( int x )
{
if( x == ufs[x] ) return 1 ;
return find_ans(ufs[x] )+1 ;
} */
int main( )
{
char ch ;
int a , b ;
init( ) ;
scanf( "%d" , &p) ;
for( int i = 0 ; i < p ; i++ )
{
getchar( ) ;
scanf( "%c" , &ch ) ;
if( ch == 'M' )
{
scanf( "%d%d" , &a ,&b ) ;
union_set(a , b) ;
}
else
{
scanf( "%d" , &a) ;
// cout << find_ans(a) <<" " <<num[find_set(a)] <<" " << endl ;
printf( "%d\n" , num[find_set(a)] - deep[a] - 1 ) ;
// printf( "%d\n" , num[find_set(a)] - find_ans(a) ) ;
}
}
return 0 ;
}
时间超限的用队列写的 ,噗 ...
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <list>
#define LL long long
#define INF 0x7fffffff
#define FIN 0x80000000
// 队列超时 ......
using namespace std;
char op[5];
int a,b;
queue<int> que[30002];
int vis[30002],ans[30002]; // vis数组记录当前编号所在的队列 ;
// 出队到要移动的那个队列时,当前那么当前节点的ans就是那个队列的size
int main()
{
for(int i=1; i<=30000; i++)
{
vis[i]=i;
que[i].push(i);
}
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",op);
if(op[0]=='M')
{
scanf("%d %d",&a,&b);
int n=vis[a];
int m=vis[b];
while(que[n].size())
{
int t=que[n].front();
que[n].pop();
ans[t]=que[m].size();
vis[t]=m;
que[m].push(t) ;
}
}
else if(op[0]=='C')
{
scanf("%d",&a);
printf("%d\n",ans[a]);
}
}
}