Why is the time complexity log (n )?
First, the idea of tree arrays is itself a tree, so the time complexity of operations is similar to that of the tree.
It can also be demonstrated through computation:
If the current node is n, the method to reach the parent node is:
N = n + n &-n (I don't know why, Baidu)
In fact, it is to move the leftmost 1 of the n binary to the left, for example, 2-10, 4-100.
The method to reach the subnode is:
N = n-n &-n
This is actually to change the leftmost 1 to 0 every time, such as 7-111,6-110,4-100.
In this way, the time complexity of binary Displacement Calculation is log (n), so the time complexity of tree array query and statistics is also log (n)
Solutions
This question can be done in many ways. The line segment tree is the easiest to think of, but the code implementation is very complicated.
In fact, this question can abstract the vertices that are colored each time into the intervals altered each time, and then sum the number of updates between the vertices to be queried.
In this way, the time can be greatly shortened. the time complexity of query and statistics is log (n)
Each node in the tree array represents a line segment. During each update, you can find all the segments previously included in B according to the features of the tree array, then add all the intervals before B to the number of dyeing times. Then, all the intervals before a are subtracted from the number of dyeing times. In this way, the number of dyeing times of [a, B] In the tree array is modified. When you query the total number of dyeing times of each vertex, you can directly calculate the value of each parent node, that is, the number of dyeing times of all intervals containing the vertex. This is a typical application of downward query and upward statistics in a tree array.
Ps: depending on the individual's understanding, this question can also be queried up, analyzed down, or queried down, but this is the easiest way to understand.
The code is implemented as follows:
Read/write operations with cin and cout will time out, so I still use scanf (), printf ()
[Cpp]
# Include <stdio. h>
# Include <string. h>
Const int MAXN = 110000;
Int n, c [MAXN];
Int lowbit (int x)
// Calculate 2 ^ k
{
X = x &-x;
Return x;
}
Void update (int num, int val)
// Query down. num is the child node to be updated, and val is the value to be modified.
{
While (num> 0)
{
C [num] + = val;
Num-= lowbit (num );
}
}
Int getSum (int num)
// Count the number of times each interval is colored up
{
Int sum = 0;
While (num <= n)
{
Sum + = c [num];
Num + = lowbit (num );
}
Return sum;
}
Int main ()
{
Int a, B;
While (scanf ("% d", & n), n)
{
Memset (c, 0, sizeof (c ));
For (int I = 0; I <n; I ++)
{
Scanf ("% d", & a, & B );
// Set the interval below B to 1
Update (B, 1 );
// Set the range below a to 1
Update (A-1,-1 );
}
For (int j = 1; j <n; j ++)
{
Printf ("% d", getSum (j ));
}
Printf ("% d \ n", getSum (n ));
}
Return 0;
}
# Include <stdio. h>
# Include <string. h>
Const int MAXN = 110000;
Int n, c [MAXN];
Int lowbit (int x)
// Calculate 2 ^ k
{
X = x &-x;
Return x;
}
Void update (int num, int val)
// Query down. num is the child node to be updated, and val is the value to be modified.
{
While (num> 0)
{
C [num] + = val;
Num-= lowbit (num );
}
}
Int getSum (int num)
// Count the number of times each interval is colored up
{
Int sum = 0;
While (num <= n)
{
Sum + = c [num];
Num + = lowbit (num );
}
Return sum;
}
Int main ()
{
Int a, B;
While (scanf ("% d", & n), n)
{
Memset (c, 0, sizeof (c ));
For (int I = 0; I <n; I ++)
{
Scanf ("% d", & a, & B );
// Set the interval below B to 1
Update (B, 1 );
// Set the range below a to 1
Update (A-1,-1 );
}
For (int j = 1; j <n; j ++)
{
Printf ("% d", getSum (j ));
}
Printf ("% d \ n", getSum (n ));
}
Return 0;
}