Cube Stacking
Time Limit:2000MS Memory Limit:30000KB 64bit IO Format:%I64d & %I64u
Submit Status
Description
Farmer John and Betsy are playing a game with N (1 <= N <= 30,000)identical cubes labeled 1 through N. They start with N stacks, each containing a single cube. Farmer John asks Betsy to perform P (1<= P <= 100,000) operation. There are two types of operations:
moves and counts.
* In a move operation, Farmer John asks Bessie to move the stack containing cube X on top of the stack containing cube Y.
* In a count operation, Farmer John asks Bessie to count the number of cubes on the stack with cube X that are under the cube X and report that value.
Write a program that can verify the results of the game.
Input
* Line 1: A single integer, P
* Lines 2..P+1: Each of these lines describes a legal operation. Line 2 describes the first operation, etc. Each line begins with a ‘M‘ for a move operation or a ‘C‘ for a count operation. For move operations, the line also contains two integers: X and Y.For count operations, the line also contains a single integer: X.
Note that the value for N does not appear in the input file. No move operation will request a move a stack onto itself.
Output
Print the output from each of the count operations in the same order as the input file.
Sample Input
6 M 1 6 C 1 M 2 4 M 2 6 C 3 C 4
Sample Output
1 0 2
并查集:ran[x] 表示 在x下面的立方体数,sum[x]表示x所在堆的总立方体数,随着立方体的叠放,sum值只记载在根节点处,在unite()中,ran值也只是记载在fx上,容易理解ran[fx] += sum[fy];在之后find()中再将一个个节点经行更新ran[x] += ran[fx];
#include<cstdio> #include<algorithm> #include<cstring> const int maxn = 3e4+5; using namespace std; int pre[maxn]; int ran[maxn]; int sum[maxn]; void init(){ for(int i = 1; i <= maxn; i++){ pre[i] = i; ran[i] = 0; sum[i] = 1; } } int find(int x){ if(pre[x] == x) return pre[x]; int fx = pre[x]; pre[x] = find(pre[x]); ran[x] += ran[fx]; return pre[x]; } void unite(int x,int y){ int fx = find(x); int fy = find(y); pre[fx] = fy; ran[fx] += sum[fy]; sum[fy] += sum[fx]; } int main(){ int p,x,y; char ch[2]; init(); scanf("%d",&p); while(p--){ scanf("%s",ch); if(ch[0] == ‘M‘){ scanf("%d%d",&x,&y); unite(x,y); } else { scanf("%d",&x); int tep = find(x); printf("%d\n",ran[x]); } } return 0; }
另外,通过这道题终于懂了并查集的find()函数,原来我之前都是一知半解= =!
举个例子说明一下:
int find(int x){ if(pre[x] == x) return pre[x]; int fx = pre[x]; pre[x] = find(pre[x]); ran[x] += ran[fx]; return pre[x]; }1 -> 2 -> 3 -> 4 -> 5;x = 1, fx = 2; -> x = 2, fx = 3; -> x = 3, fx = 4; -> x = 4, fx = 5; -> x = 5, fx = 5; pre[4] = pre[5](5); -> pre[3] = pre[4](5); -> pre[2] = pre[3](5); -> pre[1] = pre[2](5); ran[4] += ran[5]; -> ran[3] += ran[4]; -> ran[2] += ran[3]; -> ran[1] += ran[2]; 这样就形成了一颗高度为2的树,除根节点外全部节点指向根节点,搜索起来减少了不少的复杂度,膜拜!而ran值也在其中是从根节点经行更新;并查集真是so cool!