Tree array and its application

Time:2021-10-21

1. Principle of tree array

In programming, we need to maintain the prefix and s of a one-dimensional array, let s [i] = a [1] + a [2] +… + a [i].

If we modify the value of any element a [i], the related prefix and s [i], s [i + 1],…, s [n] will change. If the traditional linear sequential scanning method is used to find the sum of continuous array elements, the time complexity of adjusting the prefix and S is O (n) after each modification of A[i]. If the frequency of modifying elements in array A is m, the time complexity of adjusting prefix and S is O (m * n).

        In order to improve the efficiency of maintaining prefixes and, the “tree array” can be introduced. The tree array transforms the linear structure into a pseudo tree structure (the linear structure can only scan the elements one by one, while the tree structure can realize skip scanning), so that the time complexity of maintaining the prefix and sum is O (log) after modifying the element value of the array2n) So as to greatly improve the overall efficiency.

There is an array a [n], and the corresponding tree array is C [n]. When n = 9, its tree structure is shown in Figure 1.

Figure 1   Tree array structure diagram

In Figure 1, let the black array elements a [1] ~ a [8] represent the original array a, and the red array elements C [1] ~ C [8] represent the tree array C. If each node element in the graph stores the sum of its child node element values, there is

C[1] = A[1];

C[2] = A[1] + A[2];

C[3] = A[3];

C[4] = A[1] + A[2] + A[3] + A[4];

C[5] = A[5];

C[6] = A[5] + A[6];

C[7] = A[7];

C[8] = A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8];

It can be found that the values of the elements of the tree array are regular

C[i] = A[i – 2k+1] + A[i – 2k+2] + … + A[i];    //  K is the tag number of the rightmost 1 in the binary of I

For example, when I = 6, the binary number is 110 and the position of the rightmost 1 is 1, so k = 1, C [6] = a [6-2 + 1] + a [6];

When I = 8, the binary number is 1000 and the position of the rightmost 1 is 3, so k = 3, C [8] = a [8-8 + 1] +… + a [8].

(1) Find the prefix sum.

Let’s first look at how to use tree array C to find the sum of the first I items in array a.

For example, when I = 5,

S[5]=A[1]+A[2]+A[3]+A[4]+A[5] ; 

As shown in Figure 1, C [4] = a [1] + a [2] + a [3] + a [4];    C[5]=A[5];

Therefore:    S[5]=C[4]+C[5];

The serial number is written in binary: s [(101)] = C [(100)] + C [(101)].

For another example, when I = 7,

S[7]=A[1]+A[2]+A[3]+A[4]+A[5]+A[6]+A[7] ; 

As shown in Figure 1, C [4] = a [1] + a [2] + a [3] + a [4];    C[6]=A[5]+A[6];    C[7]=A[7];

Therefore:    S[7]=C[4]+C[6]+C[7];

The serial number is written in binary: s [(111)] = C [(100)] + C [(110)] + C [(111)];

Looking at the above two examples, the essence of tree array is the application of binary.

Thus, the operation of summing prefixes can be written as the following function:

int getsum(int i)

{

    int res = 0;

    while(i > 0)

    {

        res += c[i];

        i -= lowbit(i);

    }

    return res;

}

The return value of function lowbit (I) is 2k, K is the tag number of the rightmost 1 in the binary of I.

Next, take I = 7 as an example to simulate the execution process of the function getsum (7).

I = 7 (binary number is 111), res + = C [7] = C [7], lowbit (7) = 001 (binary representation, corresponding to 1), I = 7-1 = 6;

I = 6 (binary number is 110), res + = C [6], lowbit (6) = 010 (binary representation, corresponding to 2), I = 6-2 = 4;

I = 4 (binary number is 100), res + = C [4], lowbit (4) = 100 (binary representation, corresponding to 4), I = 4-4 = 0;

I = 0, end the cycle and return res (= C [7] + C [6] + C [4]).

In this way, the tree array can quickly sum any interval [a, b]: a [a] + a [a + 1] +… + a [b], and directly call getsum (b) – getsum (A-1).

(2) Single point update.

Next, we will discuss how to generate and maintain tree arrays.

When modifying the value of an element a [i] in array a   How should I update the array tree c?

When modifying the value of a [i], you can trace from C [i] to the root node and adjust all C [k] on this route.

For example, when modifying a [1], you need to update C [1], C [2], C [4] and C [8] upward, which is expressed as binary corresponding to:

         C[(001)]、C[(010)]、C[(100)]、C[(1000)]

For another example, when modifying a [5], you need to update C [5], C [6] and C [8] upward, which is expressed as binary corresponding to:

       C[(101)]、C[(110)]、C[(1000)]

Looking at the above two examples, single point update and prefix sum are mutually inverse operations.

Thus, the operation of single point update can be written as the following function:

void update(int i,int value)    // After modifying the value of a [i] to increase value, update the tree array

{

    while (i<=n)

    {

        c[i]+=value;

        i+=lowbit(i);

    }

}

Next, take modifying a [5] as an example to simulate the execution process of function update (5, Val).

I = 5 (binary number is 101), C [5] + = Val, lowbit (5) = 001 (binary representation, corresponding to 1), I = 5 + 1 = 6;

I = 6 (binary number is 110), C [6] + = Val, lowbit (6) = 010 (binary representation, corresponding to 2), I = 6 + 2 = 8;

I = 8 (binary number is 1000), C [8] + = Val, lowbit (8) = 10000 (binary representation, corresponding to 16), I = 8 + 16 = 24;

I = 24 > N, end the cycle. During the cycle, C [5], C [6], C [8] are updated.

With the single point update function, it is easy to construct the corresponding tree array C according to the given array a. Initially, make all the element values of array C 0, and call the function update (I, a [i]) successively with the element values a [1] ~ a [n] of array a to construct the corresponding tree array C.

(3) Implementation of lowbit function.

        The return value of the function lowbit (I) is 2k, K is the tag number of the rightmost 1 in the binary of I. This can be simply implemented by an expression I & (- I), that is, 2 ^ k = I & (- I).

Here, the storage characteristics of negative numbers are used. In the computer, negative integers are stored in complement. For integer operation x& (- x), there are:

1) When I is 0, i.e. 0 & 0, the result is 0;

2) When I is an odd number, the last bit is 1, and the inverse plus 1 has no carry. Therefore, except for the last bit, the previous bits of X and – X are exactly the opposite (the bitwise and result is 0), the last bit is 1, and the bitwise and subsequent result is 1.

3) When I is an even number and is the m-th power of 2, only one bit in the binary representation of X is 1 (set as the M + 1 bit from right to left), and there is m-bit 0 on the right. Therefore, after X takes the inverse plus 1, there is M-0 from right to left, and the M + 1 bit and its left are all 1. So, X & (- x) gets X.

4) When I is an even number, but not in the form of M-power of 2, I = y * (2 ^ k) can be written. Where, the lowest bit of Y is 1. In fact, I is represented by shifting an odd number to the left by K bits. At this time, the binary representation of I has k zeros on the far right, and the K + 1 bit from right to left is 1. When I is reversed, the rightmost k bit 0 becomes 1 and the K + 1 bit becomes 0; Plus 1, the rightmost k bit becomes 0 again, and the K + 1 bit becomes 1 because of the carry relationship. Because there is no carry, the left bit is just the opposite of the value on the original corresponding bit of I. By bitwise and, we get: 1 on the K + 1 bit, 0 on the left and right. The result is 2 ^ K.

2. Application of tree array

Next, we introduce the application of tree array through an example.

two point one   Single point update and interval query

Update an element of a given array, and then query the sum value of the interval.

Example 1   [template] tree array 1

This question is from the Luogu question bank( https://www.luogu.com.cn/problem/P3374 )

Title Description

Given a sequence of numbers, you need to perform the following two operations:

Add x to a number

Find the sum of each number in an interval

Input format

The first row contains two positive integers n and m, which respectively represent the number of numbers in the sequence and the total number of operations.

The second row contains n integers separated by spaces, where the i-th number represents the initial value of the i-th item of the sequence.

The next M lines contain 3 integers, representing an operation, as follows:

1 x k means: add K to the x-th number

2 x y meaning: the sum of each number in the output interval [x, y]

Output format

The output contains several lines of integers, which is the result of all operations 22.

sample input

5 5

1 5 4 2 3

1 1 3

2 2 5

1 3 -1

1 4 2

2 1 4

sample output

14

16

(1) Programming ideas.

Typical tree array application template questions. Write and call the three functions described above directly.

(2) Source program.

#include

#include

int n;

int c[500001];

int lowbit(int x)

{

    return x&(-x);

}

void update(int i,int value)

{

    while (i<=n)

    {

        c[i]+=value;

        i+=lowbit(i);

    }

}

int getsum(int i)

{

    int res = 0;

    while(i > 0)

    {

        res += c[i];

        i -= lowbit(i);

    }

    return res;

}

int main()

{

    int m;

    scanf(“%d%d”,&n,&m);

    memset(c, 0, sizeof c);

    int i,p,x,y;

    for (i=1;i<=n;i++)

    {

        scanf(“%d”,&x);

        update(i,x);

    }

    for (i=1;i<=m;i++)

    {

        scanf(“%d%d%d”,&p,&x,&y);

        if (p==1) update(x,y);

        else printf(“%d\n”,getsum(y)-getsum(x-1));

    }

    return 0;

}

two point two   Interval update, single point query

With array a [n], what should I do if I want to add K or subtract K from the values of all elements in the interval [x, y], and then query the value of an element a [i]?

If you directly use the initial element values of array a to establish tree array C, then update each value in the [x, y] interval, and finally use getsum (I) – getsum (i-1) to obtain the value of element a [i] to be queried. The complexity of this approach is certainly not feasible. The best way is to introduce difference and use difference to build trees.

Set an array a [n + 1], and let a [0] = 0, using the formula B [i] = a [i] – a [I-1]   (1 ≤ I ≤ n) establish difference fraction group B.

Obviously, a [i] = B [1] + B [2] + B [3] +… + B [i]

                      =A[1]-A[0]+A[2]-A[1]+…+A[i]-A[i-1] =A[i]

Thus, the value of the array element a [i] to be queried is the sum of the first I items of the difference fraction group B.

When the values of all elements (a [x] ~ a [y]) in the interval [x, y] of array a add K or subtract K, the difference of elements in the interval is unchanged. Therefore, for the corresponding B array, only B [x] add K or subtract K, B [y + 1] subtract K or add K, and the values of other elements remain unchanged.

In this way, we use the difference fraction group B to construct the tree array C, and only two single point modifications are made for each interval modification.

Example 2   [template] tree array 2

This question is from the Luogu question bank( https://www.luogu.com.cn/problem/P3368 )

Title Description

Given a sequence of numbers, you need to perform the following two operations:

Add x to each number in an interval;

Find the value of a number.

Input format

The first row contains two integers n and m, which respectively represent the number of numbers in the sequence and the total number of operations.

The second row contains n integers separated by spaces, where the i-th number represents the initial value of the i-th item of the sequence.

Next, line m contains 2 or 4 integers, representing an operation, as follows:

Operation 1: Format: 1 x y k meaning: add K to each number in the interval [x, y];

Operation 2: Format: 2 x meaning: output the value of the x-th number.

Output format

The output contains several lines of integers, which is the result of all operations 22.

sample input

5 5

1 5 4 2 3

1 2 4 2

2 3

1 1 5 -1

1 3 5 7

2 4

sample output

6

10

(1) Programming ideas.

Typical interval update and single point query template questions. A tree array is constructed by using the difference between adjacent elements of the array.

(2) Source program.

#include

#include

int n;

int a[500001],c[500001];

int lowbit(int x)

{

    return x&(-x);

}

void update(int i,int value)

{

    while (i<=n)

    {

        c[i]+=value;

        i+=lowbit(i);

    }

}

int getsum(int i)

{

    int res = 0;

    while(i > 0)

    {

        res += c[i];

        i -= lowbit(i);

    }

    return res;

}

int main()

{

    int m,i;

    scanf(“%d%d”,&n,&m);

    memset(c, 0, sizeof c);

    for (i = 1; i<=n; i++)

    {

        scanf(“%d”,&a[i]);

        update(i,a[i] – a[i-1]);

    }

    for (i=1;i<=m;i++)

    {

        int f,x,y,k;

        scanf(“%d”,&f);

        if (f==1)

        {

            scanf(“%d%d%d”,&x,&y,&k);

            update(x,k);

            update(y+1,-k);

        }

        if (f==2)

        {

            scanf(“%d”,&x);

            printf(“%d\n”,getsum(x));

        }

    }

    return 0;

}

Example 3   Color the ball

This question is from the OJ question bank of Hangzhou University of Electronic Science and technology( http://acm.hdu.edu.cn/showproblem.php?pid=1556 )。

Problem Description

N balloons are arranged in a row, numbered 1, 2, 3… N from left to right. Each time two integers a and B (a < = b) are given, Lele will paint each balloon once from balloon a to balloon B in order to ride his “Flying Pigeon” electric car. But after n times, Lele has forgotten that the I balloon has been painted several times. Can you help him calculate how many times each balloon has been painted?

Input

The first line of each test instance is an integer n, (n < = 100000). The next N lines include 2 integers a and B (1 < = a < = B < = n).

When n = 0, the input ends.

Output

Each test instance outputs a line, including n integers. The i-th number represents the total number of times the i-th balloon is colored.

Sample Input

3

1 1

2 2

3 3

3

1 1

1 2

1 3

0

Sample Output

1 1 1

3 2 1

(1) Programming ideas.

There is an array a [n + 1], and the value of a [i] represents the number of times the balloon numbered I is colored. Initially, the element values are all 0. Color each balloon successively from balloon a to balloon B, which is equivalent to adding 1 to each element in the interval [a, b] of array a. If the difference array B of array A is defined (the initial value of the difference array is obviously all 0), add 1 to each element in the interval [a, b] of array a, and you only need to make a single point modification to the two elements B [a] and B [B + 1] of array B, where B [a] increases 1 and B [B + 1] decreases 1.

According to the principle of tree array, the value of a [i] is the sum of the first I items of difference array B, and you can call the function getsum (I).

(2) Source program.

#include

#include

int n;

int c[100001];

int lowbit(int x)

{

    return x&(-x);

}

void update(int i,int value)

{

    while (i<=n)

    {

        c[i]+=value;

        i+=lowbit(i);

    }

}

int getsum(int i)

{

    int res = 0;

    while(i > 0)

    {

        res += c[i];

        i -= lowbit(i);

    }

    return res;

}

int main()

{

    while (scanf(“%d”,&n) && n!=0)

    {

        memset(c, 0, sizeof c);

        for (int i=1; i<=n; i++)

        {

            int a,b;

            scanf(“%d%d”,&a,&b);

            update(a, 1);       

            update(b + 1, -1);    

        }

        for (int i = 1; i

        {

            printf(“%d “,getsum(i));

        }

        printf(“%d\n”,getsum(n));

    }

    return 0;

}

Example 4   Matrix

This question is from the OJ question bank of Peking University( http://poj.org/problem?id=2155 )。

Description

Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. Initially we have A[i, j] = 0 (1 <= i, j <= N).

We can change the matrix in the following way. Given a rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2), we change all the elements in the rectangle by using “not” operation (if it is a ‘0’ then change it into ‘1’ otherwise change it into ‘0’). To maintain the information of the matrix, you are asked to write a program to receive and execute two kinds of instructions.

1. C x1 y1 x2 y2 (1 <= x1 <= x2 <= n, 1 <= y1 <= y2 <= n) changes the matrix by using the rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2).

2. Q x y (1 <= x, y <= n) querys A[x, y].

Input

The first line of the input is an integer X (X <= 10) representing the number of test cases. The following X blocks each represents a test case.

The first line of each block contains two numbers N and T (2 <= N <= 1000, 1 <= T <= 50000) representing the size of the matrix and the number of the instructions. The following T lines each represents an instruction having the format “Q x y” or “C x1 y1 x2 y2”, which has been described above.

Output

For each querying output one line, which has an integer representing A[x, y].

There is a blank line between every two continuous test cases.

Sample Input

1

2 10

C 2 1 2 2

Q 2 2

C 2 1 2 1

Q 1 1

C 1 1 2 1

C 1 2 1 2

C 1 1 2 2

Q 1 1

C 1 1 2 1

Q 2 1

Sample Output

1

0

0

1

(1) Programming ideas.

Given an n * n matrix A, the element values in the matrix are not 0, that is, 1. Initially, the element values are all 0. Invert each element in the sub matrix [x1, Y1, X2, Y2] (X1 and Y1 represent the subscript of the element in the upper left corner of the sub matrix, X2 and Y2 represent the coordinate of the element in the lower right corner of the sub matrix) (0 becomes 1, 1 becomes 0), and query the value of element a [x] [y] in the matrix.

According to the characteristic that the element value of matrix A in the title is either 1 or 0, we only need to record the change of each element value several times to get the value of each element.

It can be seen from example 3 that when the array is one-dimensional, if you want to modify the value of the [x, y] interval, you only need to modify the values of X and y + 1 (add 1 to the point x value and subtract 1 from the point y + 1 value). When querying the value of point K, call the function getsum (k).

When the array is two-dimensional, the solution is similar to one-dimensional. To modify the range [x1, Y1, X2, Y2], just modify the four points: (x1, Y1), (x1, Y2 + 1), (x2 + 1, Y1), (x2 + 1, Y2 + 1). When querying the value of point (x, y), call the function getsum (x, y).

According to the principle of tree array, it is necessary to modify the single point modification and prefix sum function to two-dimensional processing.

(2) Source program.

#include

#include

int n;

int c[1001][1001];

int lowbit(int x)

{

    return x&(-x);

}

void update(int x, int y, int value)

{

    for (int i = x; i<= n; i+=lowbit(i))

       for (int j=y; j<= n; j+=lowbit(j))

          c[i][j]+=value;

}

int getsum(int x, int y)

{

    int res = 0;

    for (int i = x; i>0; i-=lowbit(i))

        for (int j = y; j > 0; j -= lowbit(j))

            res += c[i][j];

    return res;

}

int main()

{

    int t;

    scanf(“%d”,&t);

    while(t–)

    {

        int m,x1,y1,x2,y2;

        scanf(“%d%d”, &n, &m);

        memset(c, 0, sizeof(c));

        char op[5];

        while (m–)

        {

            scanf(“%s%d%d”, op, &x1, &y1);

            if (op[0] == ‘C’)

            {

                scanf(“%d%d”, &x2, &y2);

                update(x1, y1, 1);

                update(x1, y2+1, 1);

                update(x2+1, y1, 1);

                update(x2+1, y2+1, 1);

            }

            else

            {

                printf(“%d\n”, getsum(x1,y1) %2);

            }

        }

        printf(“\n”);

    }

    return 0;

}

Example 5   Flowers

This question is from the OJ question bank of Hangzhou University of Electronic Science and technology( http://acm.hdu.edu.cn/showproblem.php?pid=4325 )。

Problem Description

As is known to all, the blooming time and duration varies between different kinds of flowers. Now there is a garden planted full of flowers. The gardener wants to know how many flowers will bloom in the garden in a specific time. But there are too many flowers in the garden, so he wants you to help him.

Input

The first line contains a single integer t (1 <= t <= 10), the number of test cases.

For each case, the first line contains two integer N and M, where N (1 <= N <= 10^5) is the number of flowers, and M (1 <= M <= 10^5) is the query times.

In the next N lines, each line contains two integer Si and Ti (1 <= Si <= Ti <= 10^9), means i-th flower will be blooming at time [Si, Ti].

In the next M lines, each line contains an integer Ti, means the time of i-th query.

Output

For each case, output the case number as shown and then print M lines. Each line contains an integer, meaning the number of blooming flowers.

Sample outputs are available for more details.

Sample Input

2

1 1

5 10

4

2 3

1 4

4 8

1

4

6

Sample Output

Case #1:

0

Case #2:

1

2

1

(1) Programming ideas 1.

There are n flowers and m time points. The I flower is opening at Si and Ti. How many flowers are opening at Mi time point?

Similar to the programming idea of example 3. At the beginning, there were no flowers at all time points. The time when the ith flower is opening is Si and Ti, which is equivalent to adding 1 to each element in the interval [Si, Ti] (one flower opens). Ask how many flowers are blooming at the MI time point, and call the function getsum (MI) to get the result.

First define the size of the tree array as int c [100005];, Example 3 write the following source program.

(2) Acceptable but defective source programs.

#include

#include

int n;

int c[100005];

int lowbit(int x)

{

    return x&(-x);

}

void update(int i,int value)

{

    while (i<=100005)

    {

        c[i]+=value;

        i+=lowbit(i);

    }

}

int getsum(int i)

{

    int res = 0;

    while(i > 0)

    {

        res += c[i];

        i -= lowbit(i);

    }

    return res;

}

int main()

{

    int t;

    scanf(“%d”,&t);

    for (int k=1;k<=t;k++)

    {

        memset(c, 0, sizeof c);

        int m;

        scanf(“%d%d”,&n,&m);

        int i,s,t;

        for (i=1; i<=n; i++)

        {

            scanf(“%d%d”,&s,&t);

            update(s, 1);

            update(t + 1, -1);

        }

        printf(“Case #%d:\n”,k);

        for (i = 1; i<=m; i++)

        {

            scanf(“%d”,&t);

            printf(“%d\n”,getsum(t));

        }

    }

    return 0;

}

After the source program is submitted to the OJ system, it can be accepted. But in fact, there is a problem with this program, because the data range of Si and Ti is 1 < = Si < = Ti < = 10 ^ 9, and the maximum array C defined in the program is 100005. Accepted because the test data set is too weak and deviates from the data description in the title. If the Si or Ti entered in the test data is greater than 10 ^ 5, the program will run incorrectly. However, it is unrealistic to define array C as int c [10e9 + 1], because array C will be too large to compile.

(3) Programming ideas 2.

According to the meaning of the question, the range of Si and Ti data input is 1 < = Si < = Ti < = 10 ^ 9, while the range of flower number n is 1 < = n < = 10 ^ 5. Each flower opens at two time points, and the range of query time point number m is 1 < = n < = 10 ^ 5. Therefore, we can find a way to reduce the data in the range of 1 ~ 10 ^ 9 to 1 ~ 3 * 10 ^ 5. In order to reduce the larger data range to a smaller data range, discretization can be carried out.

The processing method of discretization is to arrange the original data in order from small to large, then rank the data (the same data rank is the same), and then each original data is represented by its rank.

Take the test sample as an example.

For example, the opening time points of two flowers are 1, 4 and 4 and 8 respectively, and the three query time points are 1, 4 and 6. The seven time points are sorted from small to large as 1, 1, 4, 4, 6 and 8, and the corresponding ranking is 1, 1, 2, 2, 3 and 4. After discretization, 1 is represented by 1, 4 is represented by 2, 6 is represented by 3, and 8 is represented by 4.

For another example, the opening time points of the three flowers are 100, 420420, 8900 and 123456789, 987654321 respectively, and the four query time points are 10, 400, 6000 and 87654. The 10 time points are sorted from small to large as follows:

10. 100, 400, 420, 420, 6000, 8900, 87654, 123456789, 987654321, and the corresponding ranking is 1, 2, 3, 4, 4, 5, 6, 7, 8, and 9. After discretization, 10 is represented by 1, 100 is represented by 2, 400 is represented by 3, 420 is represented by 4,…, and 987654321 is represented by 5.

After discretization, the tree array can be used to solve the problem.

(4) The source program for correct discretization.

#include

#include

#include

using namespace std;

struct node

{

    int id,x;

};

struct node a[300005];

int c[300005],rankk[300005];

bool cmp(struct node a,struct node b)

{

    return a.x

}

int lowbit(int x)

{

    return x&(-x);

}

void update(int i,int n,int value)

{

    while (i<=n)

    {

        c[i]+=value;

        i+=lowbit(i);

    }

}

int getsum(int i)

{

    int res = 0;

    while(i > 0)

    {

        res += c[i];

        i -= lowbit(i);

    }

    return res;

}

int main()

{

    int t;

    scanf(“%d”,&t);

    for (int k=1;k<=t;k++)

    {

        int n,m;

        scanf(“%d%d”,&n,&m);

        memset(c,0,sizeof(c));

        memset(rankk,0,sizeof(rankk));

        int temp=2*n+m,i;

        for (i=1;i<=temp;i++)

        {

             scanf(“%d”,&a[i].x);

             a[i].id=i;

        }

        sort(a+1,a+1+temp,cmp);

        int cnt=1;

        rankk[a[1].id]=cnt;

        for (i=2;i<=temp;i++)

        {

if(a[i].x==a[i-1].x)     // Weight judgment

                rankk[a[i].id]=cnt;

            else

                rankk[a[i].id]=++cnt;

        }

        for (i=1;i<2*n;i+=2)

        {

             update(rankk[i],cnt,1);

             update(rankk[i+1]+1,cnt,-1);

        }

        printf(“Case #%d:\n”,k);

        for (i=2*n+1;i<=temp;i++)

        {

            printf(“%d\n”,getsum(rankk[i]));

        }

    }

    return 0;

}

two point three   Interval update and interval query

        According to the principle of tree array introduced earlier, the essence of tree array is to realize a tree array with a time complexity of O (log2n)Single point update, interval query”, deform it and use the difference to build a tree array, which can realize “interval update and single point query”. So, how to realize “interval update, interval query”?

Set an array a [n + 1], and let a [0] = 0, using the formula C [i] = a [i] – a [I-1]   (1 ≤ I ≤ n) establish difference fraction group C.

Observation formula:

a[1]+a[2]+…+a[n]

=(a[1]-0)+(a[1]-0+a[2]-a[1])+…+ (a[1]-0 +a[2]-a[1]+…+a[n]-a[n-1])

= (c[1]) + (c[1]+c[2]) + … + (c[1]+c[2]+ … +c[n]) 

= n*c[1] + (n-1)*c[2] +… +c[n]

= n * (c[1]+c[2]+…+c[n]) – (0*c[1]+1*c[2]+…+(n-1)*c[n])

Then create a tree array C2, where C2 [i] = (i-1) * C [i], so,

a[1]+a[2]+…+a[n] = n* getsum (c,n) – getsum (c2,n)  

//Where getsum (C, n) represents the sum of the first n items of tree array C

The sum of the intervals x to y is:

(y* getsum (c,y) – getsum (c2,y))- ((x-1)* getsum (c,x-1) – getsum (c2,x-1))

Example 6   [template] segment tree 1

This question is from the Luogu question bank( https://www.luogu.com.cn/problem/ P3372)

Title Description

Given a sequence of numbers, you need to perform the following two operations:

Add K to every number in an interval.

Find the sum of each number in an interval.

Input format

The first row contains two integers n and m, which respectively represent the number of numbers in the sequence and the total number of operations.

The second row contains n integers separated by spaces, where the i-th number represents the initial value of the i-th item of the sequence.

The next M lines contain 3 or 4 integers, representing an operation, as follows:

1 x y k: add K to each number in the interval [x, y].

2 x y: sum of each number in the output interval [x, y].

Output format

The output contains several lines of integers, which is the result of all operation 2.

sample input

5 5

1 5 4 2 3

2 2 4

1 2 3 2

2 3 4

1 1 5 1

2 1 4

sample output

11

8

20

(1) Programming ideas.

Typical interval update and interval query template questions. The tree array C1 is constructed by using the difference between the adjacent elements of the array, and then the tree array C2 is constructed by using the tree array C1.

(2) Source program.

#include

#include

typedef long long LL;

#define MAXN 100001

LL n;

LL c1[MAXN],c2[MAXN];

LL lowbit(LL x)

{

       return x&(-x);

}

 

void update(LL x,LL value,LL *c)

{

       while(x<=n)

    {

              c[x]+=value;

              x+=lowbit(x);

       }

}

LL getsum(LL x,LL *c)

{

       LL sum=0;

       while(x>0)

    {

              sum+=c[x];

              x-=lowbit(x);

       }

       return sum;

}

int main()

{

       int q,op;

       LL x,y,d;

       scanf(“%lld%d”,&n,&q);

    memset(c1,0,sizeof(c1));

       memset(c2,0,sizeof(c2));

       y=0;

       for (int i=1;i<=n;++i)

       {

           scanf(“%lld”,&x);

           d=x-y;

           update(i,d,c1);

           update(i,(i-1)*d,c2);

           y=x;

       }

       for(int i=0;i

    {

           scanf(“%d”,&op);

              if (op==1)

              {

                     scanf(“%lld%lld%lld”,&x,&y,&d);

                     update(x,d,c1);

                     update(y+1,-d,c1);

                     update(x,(x-1)*d,c2);

                     update(y+1,-y*d,c2);

              }

        else

        {

                     scanf(“%lld%lld”,&x,&y);

                     printf(“%lld\n”,getsum(y,c1)*y-getsum(x-1,c1)*(x-1) -getsum(y,c2)+getsum(x-1,c2));

              }

       }

       return 0;

}