Tree array summary, tree Summary
Tree array Diagram
This figure shows the changes to the array, so that c [1] = a [1], c [2] = a [1] + a [2], c [3] = a [3], c [4] = a [1] + a [2] + a [3] + a [4]. The value of each c [I] represents the controllable interval of the corresponding I. If a value is changed, you only need to change the c [I] in the c array to control this range.
1. Tree array, two basic operations, modification and query
The first condition is a function like a god.
Int c [100010];
Int lowbit (int x)
{
Return x &-x;
} This function enables I-= lowbit (I) to jump to the node I + = lowbit (I) before the I control interval to the node after the I control interval, that is to say, you can jump from I to the position where the next control interval includes I.
Modify
Void add (int I, int n, int d)
{
While (I <= n)
{
C [I] + = d;
I + = lowbit (I );
}
}
Query
Int sum (int I)
{
Int a = 0;
While (I)
{
A + = c [I];
I-= lowbit (I );
}
Return;
}
In this modification, the value of the control interval containing I in all the c arrays is modified from the front to the back, and the entire value is searched from the back to the back at the time of log (n ).
2. You can modify not only one value, but also all values in the interval in the tree array.
1. if a value in the array is queried each time, the tree array is used to save more time than the line tree. For example, if you want to modify the value in [x, y, array a can be used to retain the initial condition. array B indicates the modification condition (B [I] indicates all the numbers from I to n + B [I]). [x, y] can be expressed as B [x] + = 1, B [y + 1] + =-1; in this way, in the tree array written by array B, when I is calculated, B [1] + B [2] + B [3]. B [I] indicates all changes to I
2. if you are querying for a range and, you can also use a tree array to write it out. The same as array a, the original condition is retained, array B indicates the modification (B [I] indicates all the changes from I to n), then sum = Sy-Sx of the range [x, y; take Sx as an example Sx = initial value + modified value, modified value = B [1] * x + B [2] * (x-1) + .. B [x] * 1 = (x + 1) * (B [1] + B [2]. + B [x])-(B [1] * 1 + B [2] * 2 + .. B [x] * x) represents the sum of B [I] with two tree arrays, and the sum of B [I] * I
3. Two-Dimensional tree Array
Modify and query a two-dimensional tree Array
Modify
Void add (int I, int j, int n, int d)
{
Int x, y;
For (x = I; x <= n; x + = lowbit (x ))
For (y = j; y <= n; y + = lowbit (y ))
C [x] [y] + = d;
}
Query
Int sum (int I, int j)
{
Int a = 0, x, y;
For (x = I; x> 0; x-= lowbit (x ))
For (y = j; y> 0; y-= lowbit (y ))
A + = c [x] [y];
Return;
}
The principle is the same for the same dimension, but in two-dimensional c [I] [j], the sum of the rectangles from [] to [I, j]
When you modify a value, you can easily query the sum of values in a range. When you modify a range, you can easily query the value of a number.
3. three-dimensional tree Array
Modify
Int add (int I, int j, int k, int n, int d)
{
Int x, y, z;
For (x = I; x <= n; x + = lowbit (x ))
For (y = j; y <= n; y + = lowbit (y ))
For (z = k; z <= n; z + = lowbit (z ))
C [x] [y] [z] + = d;
}
Query
Int sum (int I, int j, int k)
{
Int a = 0, x, y, z;
For (x = I; x> 0; x-= lowbit (x ))
For (y = j; y> 0; y-= lowbit (y ))
For (z = k; z> 0; z-= lowbit (z ))
A + = c [x] [y] [z];
Return;
}
Same as above
4. Example
1. poj2481, which sorts s and e, ensures that all cows that are stronger than I are counted when the I-th bull is used, and the marked array is before I, use a tree array to calculate the previous quantity
2. poj2352: The Star problem. Same as above, so that each level is smaller than it will be counted before it.
3. poj2299: How many exchanges are required for the conversion of a question, which can be converted from the first one to the previous one, if the I-th item only needs to be exchanged before I and is larger than I, the question is converted to the reverse order number problem. The tree array is used to calculate the reverse order number, you can calculate the number smaller than it in the forward direction. You can use (I-sum) to calculate the number larger than it before I, or directly calculate the number larger than it in the backward direction.
4. hdu1556. Each time you modify the value of a range, ask the value of a certain number.
5. poj2182: the messy cattle stand together, and the given number indicates the number of numbers before the ox is smaller than that before the ox, so the serial number of the nth ox = is useless. Find the serial number a [I] + 1, and use the tree array to calculate the serial number k as the current number, use the second part to find the number a [I] + 1, which is the serial number of a [I. (Note that in order to prevent a sequence number from being used for multiple times, the sequence number should be left as much as possible)
6. poj3468, tree array Solution
7. poj2155: Two-Dimensional tree array. modify the number of a rectangle and ask the size of a number.
8. hdu3584, a three-dimensional tree array, same as above.
Other functions of the tree Array
You can modify the range value, but you cannot calculate the Range Sum (only one vertex can be obtained). The matrix on poj is a good example. The code is at the end
Minimum interval: if it is a single endpoint (from 1 to r) or dual endpoint (l and r) but static, the dual endpoint lg ^ 2 n, the principle is that the interval approaches
You can also implement lazy-tag in the tree pile array, which is not a common problem. I haven't called it yet.
Code: (I am in trouble)
Modify the value of the entire range (one dimension ):
# Include <cstdio>
# Include <cstring>
Using namespace std;
Int n, c [1000005];
Void chg_org (int I, int delta ){
While (I <= n ){
C [I] + = delta;
I + = I & (-I );
}
}
Int qry_org (int I ){
Int ret = 0;
While (I> 0 ){
Ret + = c [I];
I-= I & (-I );
}
Return ret;
}
Void chg_itvl (int l, int r ){
Chg_org (l, 1 );
Chg_org (r + 1,-1 );
}
Int qry_elem (int x ){
Return qry_org (x );
}
Int main () {// a sample: p2155, 1-dimension
Scanf ("% d", & n );
Memset (c, 0, sizeof c );
Int m, k, xx;
Scanf ("% d", & m );
For (int I = 0; I <m; ++ I ){
Scanf ("% d", & k, & xx );
If (k> 0)
Chg_itvl (k, xx );
Else
Printf ("% d \ n", qry_elem (xx) % 2 );
}
Return 0;
}
Minimum interval: I have joined the traditional method.
{Basic_structure-> statistics-> binary index tree}
{
The insert, query_sum function are for sum, they work dynamically.
The prep_rmq, query_min function are for rmq, they work statically only.
}
Var
Sum: array [1 .. 10000000] of int64;
Min: array [1 .. 10000000] of longint; // only static avaliable
A: array [1 .. 10000000] of longint;
N, I, t, m, q1, q2, l, r: longint;
Procedure insert (I: longint; key: longint );
// Only maintain the sum field
Var dx: longint;
Begin
Dx: = key-a [I];
A [I]: = key;
While (I <= n) do
Begin
Inc (sum [I], dx );
Inc (I, I and (-I ));
End;
End;
Fu ...... remaining full text>
What is the difference between a tree array and a line segment tree?
The two are similar in complexity, but the constant of the tree array is significantly better than that of the line tree, and the programming complexity is far less than that of the line tree.
The function of a tree array is completely covered by the line segment tree. Any problem that can be solved using a tree array can be solved using a line segment tree, but the problem that the line segment tree can solve may not be solved.
Tree arrays are extremely simple in programming. With lowbit technology, you can perform core operations on tree arrays in a few short steps, the code efficiency is much higher than that of the Line Segment tree.
In addition, when the problem is extended to high-dimensional situations, the high-dimensional tree array has the constant advantage that the high-dimensional line segment tree cannot match.