The first time I got in touch, I had nothing to summarize. I read online materials.
The merge tree stores the merge order in the process of building.
The Division tree stores quick sorting during the building process.
The merge tree is suitable for solving the ranking of a number in a certain range.
The partition tree is suitable for solving the K-number of a specific interval.
POJ is to find K big numbers. The merge tree can also be used. The second answer is to find the ranking of this number by the merge tree. The partitioning tree is faster.
For HDU 2665, the merged tree I wrote cannot be used.
Merge tree:
[Cpp]
# Include <iostream>
# Include <cstdio>
# Include <cstring>
# Include <queue>
# Include <map>
# Include <stack>
# Include <algorithm>
# Include <string>
# Define LL long
# Define LD long double
# Define eps 1e-7
# Define inf 1 <30
# Define MOD 1000000007.
# Define N 100005
Using namespace std;
Struct MergeTree {
Int left, right, mid;
} Tree [N * 4];
Int num [N], mer [20] [N];
Int n, q;
Void create (int step, int l, int r, int deep ){
Tree [step]. left = l;
Tree [step]. right = r;
Tree [step]. mid = (l + r)> 1;
If (l = r ){
Mer [deep] [l] = num [l];
Return;
}
Create (step <1, l, (l + r)/2, deep + 1 );
Create (step <1) | 1, (l + r)/2 + 1, r, deep + 1 );
Int I = l, j = (l + r)/2 + 1, p = l;
// Merge and sort the data and save the data during creation.
While (I <= (l + r)/2 & j <= r ){
If (mer [deep + 1] [I]> mer [deep + 1] [j])
Mer [deep] [p ++] = mer [deep + 1] [j ++];
Else
Mer [deep] [p ++] = mer [deep + 1] [I ++];
}
While (I <= (l + r)/2)
Mer [deep] [p ++] = mer [deep + 1] [I ++];
While (j <= r)
Mer [deep] [p ++] = mer [deep + 1] [j ++];
}
Int query (int step, int l, int r, int deep, int key ){
If (tree [step]. right <l | tree [step]. left> r)
Return 0;
If (tree [step]. left> = l & tree [step]. right <= r)
// Locate the position of the key in the sorted Array
Return lower_bound (& mer [deep] [tree [step]. left], & mer [deep] [tree [step]. right] + 1, key)-& mer [deep] [tree [step]. left];
Return query (2 * step, l, r, deep + 1, key) + query (2 * step + 1, l, r, deep + 1, key );
}
Int slove (int l, int r, int k ){
Int high = n, low = 1, mid;
// Second answer
While (low Mid = (low + high + 1)> 1;
Int cnt = query (1, l, r, 1, mer [1] [mid]);
If (cnt <= k)
Low = mid;
Else
High = mid-1;
}
Return mer [1] [low];
}
Int main (){
While (scanf ("% d", & n, & q )! = EOF ){
For (int I = 1; I <= n; I ++)
Scanf ("% d", & num [I]);
Create (1, 1, n, 1 );
While (q --){
Int l, r, k;
Scanf ("% d", & l, & r, & k );
Printf ("% d \ n", slove (l, r, k-1 ));
}
}
Return 0;
}
Partition tree:
[Cpp]
# Include <iostream>
# Include <cstring>
# Include <cstdio>
# Include <algorithm>
# Define N 100005
Using namespace std;
Struct Node {
Int left, right, mid;
} Tree [N * 4];
Int sa [N], num [20] [N], cnt [20] [N]; // sa is sorted. num records the sorting result of each layer, cnt [deep] [I] indicates the depth layer. How many of the first I numbers enter the left subtree?
Int n, q;
Void debug (int d ){
For (int I = 1; I <= n; I ++)
Printf ("% d", num [d] [I]);
Printf ("\ n ");
}
Void bulid (int step, int l, int r, int deep ){
Tree [step]. left = l;
Tree [step]. right = r;
Tree [step]. mid = (l + r)> 1;
If (l = r)
Return;
Int mid = (l + r)> 1;
Int mid_val = sa [mid], lsum = mid-l + 1 ;;
For (int I = l; I <= r; I ++)
If (num [deep] [I] <mid_val)
Lsum --; // lsum indicates how many values are required in the left subtree
Int L = l, R = mid + 1;
For (int I = l; I <= r; I ++ ){
If (I = l)
Cnt [deep] [I] = 0;
Else
Cnt [deep] [I] = cnt [deep] [I-1];
If (num [deep] [I] <mid_val | (num [deep] [I] = mid_val & lsum> 0) {// left subtree
Num [deep + 1] [L ++] = num [deep] [I];
Cnt [deep] [I] ++;
If (num [deep] [I] = mid_val)
Lsum --;
}
Else
Num [deep + 1] [R ++] = num [deep] [I];
}
// Debug (deep );
Bulid (2 * step, l, mid, deep + 1 );
Bulid (2 * step + 1, mid + 1, r, deep + 1 );
}
Int query (int step, int l, int r, int k, int deep ){
If (l = r)
Return num [deep] [l];
Int s1, s2; // s1 indicates the number of left subtree in [tree [step]. left L-1 ].
If (tree [step]. left = l)
S1 = 0;
Else
S1 = cnt [deep] L-1];
S2 = cnt [deep] [r]-s1; // s2 is the number of left subtree in [l, r]
If (k <= s2) // The number of left subtree is greater than k, recursive left subtree
Return query (2 * step, tree [step]. left + s1, tree [step]. left + s1 + s2-1, k, deep + 1 );
Int b1 = l-1-tree [step]. left + 1-s1; // b1 is the number of right subtree in [tree [step]. left L-1]
Int b2 = r-l + 1-s2; // b2 indicates the number of right subtree in [l, r ].
Return query (2 * step + 1, tree [step]. mid + 1 + b1, tree [step]. mid + 1 + b1 + b2-1, k-s2, deep + 1 );
}
Int main (){;
While (scanf ("% d", & n, & q )! = EOF ){
For (int I = 1; I <= n; I ++ ){
Scanf ("% d", & num [1] [I]);
Sa [I] = num [1] [I];
}
Sort (sa + 1, sa + n + 1 );
Bulid (1, 1, n, 1 );
While (q --){
Int l, r, k;
Scanf ("% d", & l, & r, & k );
Printf ("% d \ n", query (1, l, r, k, 1 ));
}
}
Return 0;
}
By ACM_cxlove