[Knowledge Point] segment tree

Source: Internet
Author: User

This blog post for the migration, written on March 30, 2015, does not represent my current views and views. Original address: http://blog.sina.com.cn/s/blog_6022c4720102vw6j.html

1. PrefaceA topic: give a one-dimensional array of n nodes, and do something for him each time: add x to the [L,r] range, or ask what the current value of the node I is. This is no water problem! Direct simulation is possible. But what if n<=100000? What is the number of queries over 100000? O (n^2) does not carry. The content to be introduced today is the line segment tree. This thing was mentioned earlier, and I made it up, but I didn't understand it very well at the time. Recently accidentally went to see a look, found that understand.   2. ConceptThe line tree is also a tree structure, and unlike all of its nodes, each node holds a line of segments. Let's look at his structure first:
we found that although the tree segment tree structure showed, but his each node to maintain the things and the general tree structure problem difference is still relatively large.   2. Build Line TreeThe segment tree's root node is represented by [1,n], and then its two child nodes, left and right, are splitting the segments of their parent nodes from the middle , and when N=8, mid= (1+8)/2=4 (rounded down), so the line segments represented by the child nodes are [ 1,4] and [5,8]. Build from the root node one at a time until the node's segment is a point, the leaf node. -------------------------------------------------------------------------------------------------------void buildtree (int now,int l,int R)//achievements{if (l==r){scanf ("%d", &tree[now].sum);tree[now].max=tree[now].min=tree[now].sum;return;}int mid= (L+R)/2;Buildtree (now*2,l,mid);Buildtree (now*2+1,mid+1,r);tree[now].sum=tree[now*2].sum+tree[now*2+1].sum;Tree[now].max=max (Tree[now*2].max,tree[now*2+1].max);tree[now].min=min (tree[now*2].min,tree[now*2+1].min);}------------------------------------------------------------------------------------------------------- as you can see in the code, each node needs to contain sum,max,min. However, it is not necessary at all times to list all the needs here, and how to trade-offs will be mentioned later in this article. The achievement is simple, from the root to the leaf recursion.   3. Type of problemline tree is very powerful, so there are a lot of problems on the array can be very convenient to find out. Here you can make a summary:modification Type: 1, single point plus minus (each time only one number in the array is added and minus);2, single point modification (same as); 3. Interval addition and subtraction (each time the number of [L,r] is added and reduced); 4, the interval changes (each time in [l,r] all the number of changes to the same number). Inquiry Type: 1, Single point query (query the value of a number); 2, the query interval and (find all the numbers within [l,r] and); 3, the maximum value of the query interval (find [l,r] maximum);4, the query interval minimum value (same as). These content can be arbitrarily paired, arbitrarily modify the query, but generally will only appear at the same time 2, 3 kinds. The line tree each point needs to maintain the variable, is based on what it requires to join. Why are there several items that have been added red ? Because of these types, these are the hardest and most important and need to be focused.   <1> Single-point plus/minus/single-point modification------------------------------------------------------------------------------------------------------- void update1 (int now,int l,int r,int loc,int val)//Single point modification, loc represents the point to be changed, Val represents the added value{int mid= (L+R)/2;Tree[now].sum+=val;if (l==r) return;if (loc>=l && loc<=mid) update1 (now*2,l,mid,loc,val);Else Update1 (now*2+1,mid+1,r,loc,val);}-------------------------------------------------------------------------------------------------------It's good to understand that from the root node to the leaf node, all the segments that contain the LOC point are modified. Single-point modification can be said together, just one more step, before the update to find the original value and the difference between the values to be modified, in the single-point plus minus operation.   <2> interval Plus and minus-------------------------------------------------------------------------------------------------------void update2 (int now,int l,int r,int ql,int qr,int val)//Interval modification, QL and QR for Query section, Val for added value{if (l==ql && r==qr) {tree[now].sum+=val* (r-l+1), tree[now].lazy+=val; return;}//If the current segment is the one you are seekingint mid= (L+R)/2;if (tree[now].lazy!=0) pushdown (now,r-l+1);//Decentralizedif (l<=ql && mid>=qr) update2 (now*2,l,mid,ql,qr,val);//If the line segment is included in the left son of the current segmentelse if (mid+1<=ql && r>=qr) update2 (now*2+1,mid+1,r,ql,qr,val);//Right sonelse//The line segment is part of the left son's right son, so it can be updated separately{Update2 (now*2,l,mid,ql,mid,val);Update2 (now*2+1,mid+1,r,mid+1,qr,val);}tree[now].sum=tree[now*2].sum+tree[now*2+1].sum;//Put up}-------------------------------------------------------------------------------------------------------interval Plus and minus is a bit of a hassle. First, regardless of the pushdown function. The trouble is that the line tree itself is an optimization, and without this optimization, the efficiency of the segment tree will become lower. We consider a problem: assuming that the first increase in [2,6] is 2, and in [5,7] increased by 5, then in [5,6] not the equivalent of 7 increase? In the absence of an inquiry, we can steal a little lazy-for each line segment, plus a lazy logo, when no query, you can not need to go to the tree to update. at the time of the update, we do not add or subtract the value of the segment tree itself, just modify the variable lazy. Perhaps my thinking is more complex, but the same can be normal understanding. You didn't read it? In fact, can be said very image: Autumn, you are a monk in the temple, the abbot gave you a task: sweeping the yard of leaves. As we all know, the leaves fall in the autumn will continue to fall, so after sweeping over, after a while there are leaves. In the case where the abbot hasn't come to check your work, you can steal a little lazy--let the leaves pile up there! Anyway, the early sweep of the late sweep is sweeping, but not as late as the sweep it? (Still don't understand you still abandon cure to forget. )now, can the function of pushdown know? that is, the lazy ID saved by the current segment is freed up to update the true value of the segment tree. when do you want to use it? If you understand that the principle should already be known-two cases, when you need to work on a child node of a line tree labeled the Lazy ID, you have to update it, and when the query operation is required (that is, when the abbot comes over = =), it is updated. ----------------------------------------------------------------------------------------------------------- ------void Pushdown (Long long Now,long long m)//Interval modification--lazy tag devolution{tree[now*2].lazy+=tree[now].lazy; tree[now*2+1].lazy+=tree[now].lazy;tree[now*2].sum+=tree[now].lazy* (M-(M/2));tree[now*2+1].sum+=tree[now].lazy* (M/2);tree[now].lazy=0;}----------------------------------------------------------------------------------------------------------- ------        <3> Single-point querydirectly on the code. ----------------------------------------------------------------------------------------------------------- ------int getval (int now,int l,int r,int loc)//single-point query{int mid= (L+R)/2;if (l==r && r==loc) return tree[now].val;else if (loc>=l && loc<=mid) return Getval (Now*2,l,mid,loc);else return getval (now*2+1,mid+1,r,loc);} ----------------------------------------------------------------------------------------------------------- ------  <4> query interval and/MAX/min valuesIt is not difficult to notice that the Pushdown function mentioned above needs to be used here. ----------------------------------------------------------------------------------------------------------- ------int getsum (int now,int l,int r,int ql,int qr)//Interval and{if (l==ql && R==QR) return tree[now].sum;int mid= (l+r)/2,ans;if (tree[now].lazy!=0) pushdown (now,r-l+1);if (ql>=l && qr<=mid) ans=getsum (NOW*2,L,MID,QL,QR);else if (ql>=mid+1 && qr<=r) ans=getsum (NOW*2+1,MID+1,R,QL,QR);Else Ans=getsum (now*2,l,mid,ql,mid) +getsum (NOW*2+1,MID+1,R,MID+1,QR);return ans;}----------------------------------------------------------------------------------------------------------- ------here only the interval and the code, the maximum minimum value of the same, we have to write.  The line tree is finished, and the complete code is combined with the above functions.

[Knowledge Point] segment tree

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.