Http://poj.org/problem? Id = 2985
The tree array is amazing. In the past, it could still find elements smaller than K... orz, and calculate V5!
# Define N (1 <20) int C [N], rank [N], Fa [N]; int n, m; void Init () {int I; for (I = 1; I <n; I ++) {C [I] = 0; Fa [I] = I; rank [I] = 1 ;}} int lowbit (int x) {return X & (-x);} int find (int x) {If (X! = Fa [x]) {Fa [x] = find (Fa [x]);} return Fa [X];} void add (int id, int V) {While (ID <n) {C [ID] + = V; ID + = lowbit (ID) ;}} int sum (int x) {int ans = 0; while (x) {ans + = C [X]; X-= lowbit (x);} return ans;} // complexity log (n) int find_k (int K) {int ans = 0, CNT = 0; For (INT I = Log (double (N-1)/log (2.0); I> = 0; I --) {// Inverse Simulation of the sum of the tree array, ANS + = (1 <I); If (ANS> = n | CNT + C [ANS]> = K) ans-= (1 <I); else CNT + = C [ANS];} return ans + 1 ;} Int main () {While (scanf ("% d", & N, & M )! =-1) {int I, j; Init (); add (1, N); While (M --) {int op; scanf ("% d ", & OP); If (OP = 0) {int A, B; scanf ("% d", & A, & B ); int Ra = find (a); int RB = find (B); If (RA = Rb) continue; add (rank [Ra],-1 ); add (rank [RB],-1); add (rank [Ra] + rank [RB], 1); Fa [Ra] = RB; rank [RB] + = rank [Ra]; n --;} else {int K; scanf ("% d", & K); k = n-k + 1; // obtain the nth-k + 1 smallest printf ("% d \ n", find_k (k) ;}} return 0 ;}
Zookeeper ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Supplement:
Tree array to find K small elements
Looking back at the definition of a tree array, we noticed that there are two properties:
1. c [ANS] = sum of a [ANS-lowbit (ANS) + 1... ANS];
2. When ans = 2 ^ K,
C [ANS] = sum of a [1... ANS];
The following describes how findk (k) works:
1. Set the boundary condition ans, ANS '<maxn and CNT <= K;
2. initialize CNT = C [ANS], where ans = 2 ^ K and K are the largest integers that meet the boundary condition;
3. Find the largest ans that meet the boundary condition so that ANS '-lowbit (ANS) = ans, that is, ANS' satisfies C [ans '] = A [ans + 1 .. ans '] (according to Nature 1), as long as C [ans'] is accumulated into CNT (CNT = sum of a [1... ans '], according to Nature 2), CNT can be used as the approximate value of K;
4. Repeat Step 1 until CNT can no longer approach K. In this case, ANS is exactly 1 smaller than the solution, and ANS + 1 is returned.
In fact, this algorithm is to reverse the sum of the tree array ........
Therefore, the essence of findk (k) is binary approximation.
# Define N (1 <20) int C [N]; // complexity log (n) int find_k (int K) {int ans = 0, CNT = 0; for (INT I = 20; I> = 0; I --) {// reverse simulation of the sum of the tree array, ANS + = (1 <I ); if (ANS> = n | CNT + C [ANS]> = k) ans-= (1 <I); else CNT + = C [ANS];} return ans + 1 ;}