Segment Tree Learning

Source: Internet
Author: User

This question test instructions very understood:

Give you n number, q operation, operation there are two, ' q a B ' is asked a~b this number of and, ' C a B C ' is to put a~b this paragraph number are added C.


Need to use segment tree, update: segment increment, query: Interval sum

Introduction Lazy thought: Lazy-tag thought, records each segment tree node change value, when this part of the line segment consistency is destroyed we will pass this change value to the sub-interval, greatly increases the line-segment tree the efficiency.

In this popular explanation I understand the lazy meaning, such as now need to the [a, b] interval value plus c operation, then from the root node [1,n] began to call the update function to operate, if just execute to a child node, its node is marked RT, then Tree[rt].l = = A && TREE[RT].R = = B At this point we can update the value of the RT node's SUM[RT] at this time, sum[rt] + = c * (TREE[RT].R-TREE[RT].L + 1), notice the key moment comes, if at this time according to the normal line segment tree Update operation, this time also should update the RT child node sum[] value, and lazy thought is just temporarily do not update the RT child node of the sum[] value, to this return, until the next time need to use the value of the RT Sub-node to update, so as to avoid many potentially useless operations, Thus saving time.

This is illustrated by the specific code below. (The function name and macro here learn the code style of small HH)

Here is a description of the function in the following code:

#define Lson l,m,rt<<1
#define Rson m+1,r,rt<<1|1


Macro definition left son Lson and right son Rson, seemingly with a macro speed to slow.

Pushup (RT): Update values recursively up to the root node via the current node RT

Pushdown (RT): The value of the RT child node is updated recursively through the current node RT

RT represents the root of the current subtree (root), which is the current node.

__int64 sum[n<<2],add[n<<2];
struct Node
{
int l,r;
int Mid ()
{
Return (L+R) >>1;
}
} tree[n<<2];
This defines the sum of the data structure sum used to store the number of child nodes of each node, and the add is used to record how much each value of that node should be added

Tree[].l TREE[].R represents the left and right intervals of a node, where the interval is a closed interval

The following is a direct introduction to the update function, the lazy operation is mainly used here
void update (int c,int l,int r,int RT)//indicates that each number in the interval [l,r] plus c,rt is the root node
{
if (TREE[RT].L = = L && r = = TREE[RT].R)
{
ADD[RT] + = C;
SUM[RT] + = (__int64) c * (r-l+1);
Return
}
if (tree[rt].l = = TREE[RT].R) return;
Pushdown (RT,TREE[RT].R-TREE[RT].L + 1);
int m = Tree[rt].mid ();
if (r <= m) update (C,L,R,RT&LT;&LT;1);
else if (L > M) update (C,L,R,RT&LT;&LT;1|1);
Else
{
Update (C,L,M,RT&LT;&LT;1);
Update (C,M+1,R,RT&LT;&LT;1|1);
}
Pushup (RT);
}
if (TREE[RT].L = = L && r = = TREE[RT].R) Here is the key moment of lazy thought as mentioned above, here first update the SUM[RT] value of the node, and then update the node specific each value should be added as much as Add[rt ] value, note that at this point the entire function runs out, directly return, instead of continuing to continue to update the child nodes, here is lazy thought, temporarily do not update the value of the child node.

So when do you need to update the values of the child nodes? The answer is that when a part of the update operation needs to use the value of the node that is not updated, there may be a bit of a detour here. The Pushdown () function is then used to update the values of the child nodes.
void pushdown (int rt,int m)
{
if (Add[rt])
{
ADD[RT&LT;&LT;1] + = Add[rt];
ADD[RT&LT;&LT;1|1] + = Add[rt];
SUM[RT&LT;&LT;1] + = add[rt] * (M-(m>>1));
SUM[RT&LT;&LT;1|1] + = add[rt] * (m>>1);
ADD[RT] = 0;//needs to be restored after update
}
}
Pushdown is to update the value of each child node from the current root node RT, and this code reader can understand it yourself, which is the key to lazy.

Next is the update operation of the three if statements, where I have been not understood, thanks to NYF teammates, thanks to the guidance.




The following explains the query function, which is to use this function to find the interval and
__int64 query (int l,int r,int RT)
{
if (L = = Tree[rt].l && r = = TREE[RT].R)
{
return SUM[RT];
}
Pushdown (RT,TREE[RT].R-TREE[RT].L + 1);
int m = Tree[rt].mid ();
__int64 res = 0;
if (r <= m) Res + = query (l,r,rt<<1);
else if (L > m) res + = query (l,r,rt<<1|1);
Else
{
Res + = query (l,m,rt<<1);
Res + = query (m+1,r,rt<<1|1);
}
return res;
}
The first if or interval judgment is the same as the previous update, so we can know the answer here, so we return directly.

The next query will need to use the value of the RT Sub-node, because we use the lazy operation, the value of this paragraph has not been updated, so we need to call the Pushdown function to update, meet if (Add[rt]) that the description has not been updated.




To here the whole lazy thought even if the introduction is over, perhaps my language organization is not very good, if there is no understanding of the place can give me a message, I explain the doubts of everyone.

PS: Today is the beginning of the line tree.

Recommended here, the full version of the line segment tree URL

The following is the POJ3468 complete code http://www.notonlysuccess.com/index.php/segment-tree-complete/, which has a very elegant line segment tree code, Indicates that its update and query writing is very clever, the amount of code is also relatively small, you can go to learn.
#include <iostream>
#include <cstdio>
using namespace Std;
const int N = 100005;
#define Lson l,m,rt<<1
#define Rson m+1,r,rt<<1|1

__int64 sum[n<<2],add[n<<2];
struct Node
{
int l,r;
int Mid ()
{
Return (L+R) >>1;
}
} tree[n<<2];

void pushup (int rt)
{
SUM[RT] = sum[rt<<1] + sum[rt<<1|1];
}

void pushdown (int rt,int m)
{
if (Add[rt])
{
ADD[RT&LT;&LT;1] + = Add[rt];
ADD[RT&LT;&LT;1|1] + = Add[rt];
SUM[RT&LT;&LT;1] + = add[rt] * (M-(m>>1));
SUM[RT&LT;&LT;1|1] + = add[rt] * (m>>1);
ADD[RT] = 0;
}
}

void build (int l,int r,int RT)
{
TREE[RT].L = l;
TREE[RT].R = R;
ADD[RT] = 0;
if (L = = r)
{
scanf ("%i64d", &sum[rt]);
return;
}
int m = Tree[rt].mid ();
Build (Lson);
Build (Rson);
Pushup (RT);
}

void update (int c,int l,int r,int RT)
{
if (TREE[RT].L = = L && r = = TREE[RT].R)
{
ADD[RT] + = C;
SUM[RT] + = (__int64) c * (r-l+1);
Return
}
if (tree[rt].l = = TREE[RT].R) return;
Pushdown (RT,TREE[RT].R-TREE[RT].L + 1);
int m = Tree[rt].mid ();
if (r <= m) update (C,L,R,RT&LT;&LT;1);
else if (L > M) update (C,L,R,RT&LT;&LT;1|1);
Else
{
Update (C,L,M,RT&LT;&LT;1);
Update (C,M+1,R,RT&LT;&LT;1|1);
}
Pushup (RT);
}

__int64 query (int l,int r,int RT)
{
if (L = = Tree[rt].l && r = = TREE[RT].R)
{
return SUM[RT];
}
Pushdown (RT,TREE[RT].R-TREE[RT].L + 1);
int m = Tree[rt].mid ();
__int64 res = 0;
if (r <= m) Res + = query (l,r,rt<<1);
else if (L > m) res + = query (l,r,rt<<1|1);
Else
{
Res + = query (l,m,rt<<1);
Res + = query (m+1,r,rt<<1|1);
}
return res;
}

int main ()
{
int n,m;
while (~SCANF ("%d%d", &n,&m))
{
Build (1,n,1);
while (m--)
{
Char ch[2];
scanf ("%s", ch);
int a,b,c;
if (ch[0] = = ' Q ')
{
scanf ("%d%d", &a,&b);
printf ("%i64d\n", Query (a,b,1));
}

Else
{
scanf ("%d%d%d", &a,&b,&c);
Update (c,a,b,1);
}
}
}
return 0;
}

Segment Tree Learning

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.