Hihocoder Week 177 — Full Binary Tree Picture (O(N)复杂度)
Problem
Idea
Some solutions gives by others need to traverse the whole full binary tree and check each nodes to get the answer. Here we put forward a solution whose time complexity is O(N) .
The key idea of the solution is to get the count of nodes in the range of [y1, y2]
in each layer. If the
x
coordinate of the layer is in the range of [x1, x2]
, we will add the count to the answer.
Note that we can mark nodes in a full binary tree with numbers from 1 to snode
and enode
denote the start node ant the end node of the satisfied nodes sequence.
In the solution, we use two variables to capture the indexes of snode
and enode
, i.e., y_min
and y_max
. Their indexes are stored in y_min_idx
and y_max_idx
. At the start of the algorithm, we initialize their values as y_min = y_max = 0
and y_min_idx = y_max_idx = 0
, for we start to go from the root.
Our algorithm can be divided into two procedures.
In the first procedure,
y_min==y_max
. And we need to check whethersnode
andenode
can go two side (left child and right child). We can see that only ify_min/y_max
is in the range of[y1, y2]
, we can bi-pathsnode
andenode
to left child and right child. This is because the range between them potentially have an intersection with [y1, y2]. Otherwisey_min/y_max
is in the outside of[y1, y2]
. This time,y_min/y_max
need to go close toy1
ory2
.In the second procedure,
y_min!=y_max
. And we need to checky_min
andy_max
to make sure whether they are in the range of[y1, y2]
. If not, fory_min
,snode
will go to its right child; fory_max
,enode
will go to its left child. We have mentioned that[y_min, y_max]
may have an intersection with[y1, y2]
. Ify_min
is out of the range, we set tempsnode
to its right sibling node. Ify_max
is out of the range, we set tempenode
to its left sibling node. If the x <script id="MathJax-Element-46" type="math/tex">x</script> coordinate of the current layer is in the range of[x1, x2]
, we add count of nodes betweensnode
andenode
.
The step (height difference) between two adjcent layer is easy to compute, and we omit here.
Code
// time: 0ms, momory: 0MB
#include <string.h>
#include <stdio.h>
int n, m;
int x1[110];
int y1[110];
int x2[110];
int y2[110];
int height[20];
void cal(int a1, int b1, int a2, int b2){
int i;
int ans = 0;
int x = 0;
int y_max = 0;
int y_min = 0;
int y_max_idx = 1;
int y_min_idx = 1;
int tmp_max, tmp_min;
if(a1 > a2 || b1 > b2){
printf("0\n");
return;
}
for(i = 1; i <= n; i++){
if(x > a2)
break;
if(y_min == y_max){
// check whether in the range
if(y_min >= b1 && y_min <= b2){
//good, go two sides
if(x >= a1){
ans++;
}
y_min -= (height[i] + 1);
y_min_idx = y_min_idx * 2;
y_max += (height[i] + 1);
y_max_idx = y_max_idx * 2 + 1;
} else {
// bad , both go one side
if(y_min < b1) {
// both go right
y_min += (height[i] + 1);
y_min_idx = y_min_idx * 2 + 1;
y_max += (height[i] + 1);
y_max_idx = y_max_idx * 2 + 1;
} else {
// both go left
y_min -= (height[i] + 1);
y_min_idx = y_min_idx * 2;
y_max -= (height[i] + 1);
y_max_idx = y_max_idx * 2;
}
}
} else {
// has go two side
tmp_max = (y_max > b2) ? (y_max_idx - 1) : y_max_idx;
tmp_min = (y_min < b1) ? (y_min_idx + 1) : y_min_idx;
// if(tmp_max >= tmp_min) {
if(x >= a1){
ans += (tmp_max - tmp_min + 1);
}
// }
if(y_max > b2){
// go left
y_max -= (height[i] + 1);
y_max_idx = y_max_idx * 2;
} else {
// continue go right
y_max += (height[i] + 1);
y_max_idx = y_max_idx * 2 + 1;
}
if(y_min < b1) {
// go right
y_min += (height[i] + 1);
y_min_idx = y_min_idx * 2 + 1;
} else {
// continue go left
y_min -= (height[i] + 1);
y_min_idx = y_min_idx * 2;
}
}
x += (height[i] + 1);
}
printf("%d\n", ans);
}
void solve(){
int i;
memset(height, 0, sizeof(height));
// calculate layer step
if(n > 1)
height[n-1] = 1;
if(n > 2)
height[n-2] = 2;
for(i = n-3; i >= 1; i--){
// for(int j = n-1; j > i; j--){
// height[i] += (height[j] + 1);
// }
height[i] = height[i+1] * 2 + 1;
}
for(int i = 0; i < m; i++){
cal(x1[i], y1[i], x2[i], y2[i]);
}
}
int main(int argc, char const *argv[])
{
int i;
#ifndef ONLINE_JUDGE
freopen("out", "r", stdin);
#endif
scanf("%d %d", &n, &m);
for(i = 0; i < m; i++){
// cin >> x1[i] >> y1[i] >> x2[i] >> y2[i];
scanf("%d %d %d %d", &x1[i], &y1[i], &x2[i], &y2[i]);
}
solve();
return 0;
}