Algorithm template--The lazy tag of line segment tree

Source: Internet
Author: User
Tags cmath

I. Preface

We already know that the segment tree is capable of single-point modification and interval query operations (basic segment tree). So what if you need to modify a range? If the violence changes to the leaf node, the complexity is \ (O (nlog_n) \), is obviously very not good. So can we reduce the complexity to the same level as the interval query (O (log_n) \) ?

Two. Algorithmic flow

The line-segment tree must have been modified by Log_n (O (r) \) , otherwise what is the use of inventing it? So, I need to know now how to quickly make interval modifications. First, we review the termination node

Assuming I want to modify the interval [2,8] on this graph, I just need to modify all the terminating nodes on the graph. The complexity is then reduced to \ (O (log_n) \).
So, what do I add to the terminating node? Here, we are going to introduce the \ (lazy\) tag. When modifying the interval, a marker is made on all the terminating nodes of the interval, which indicates how much value I want to add to this point.
Interval query, if access to a marked point, but can not use the value of the point of time, the tag is passed (a bit around, to see if the code should be clear), the other time directly to the value is good

Three. Example 1.pku3468 A simple problem with integers

Description
You have N integers, A1, A2, ..., an. You need to deal with both kinds of operations. One type of op
Eration is to add some given number to each number in a given interval. The other are to ask for the
Sum of numbers in a given interval.
1. Add a constant C to [a, b] as a whole.
2. Query the and of the [a, b] interval.

Input
The first line contains the numbers N and Q. 1≤n,q≤100000.
The second line contains N numbers, the initial values of A1, A2, ...,. -1000000000≤ai≤1000000000.
Each of the next Q lines represents an operation.
"C A B C" means adding c to each of the Aa, aa+1, ..., Ab. -10000≤c≤10000.
"Q a B" means querying the sum of Aa, aa+1, ..., Ab.

Output
You need to answer all Q commands in order. One answer in a line. The sums may exceed the range of 32-bit integers

Sample Input
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output
4
55
9
15

HINT
For 100% data: n<=100000,m<=100000

Interval modification, interval query, so use the lazy tag, the code will have detailed comments

#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include < Algorithm> #define INF 0x7f7f7f7fusing namespace std;typedef long long ll;typedef unsigned int ui;typedef unsigned long    Long Ull;inline int read () {int X=0,f=1;char ch=getchar (); for (;ch< ' 0 ' | |    Ch> ' 9 '; Ch=getchar ()) if (ch== '-') f=-1;    for (; ch>= ' 0 ' &&ch<= ' 9 '; Ch=getchar ()) x= (x<<1) + (x<<3) +ch-' 0 '; return x*f;}    inline void print (int x) {if (x>=10) print (X/10); Putchar (x%10+ ' 0 ');} const int N=1e5;int n,m;ll val[n+10];struct segment{#define LS (p<<1) #define RS (p<<1|1) ll tree[n*    4+10],CNT[N*4+10];    void Updata (int p) {tree[p]= (Tree[ls]+tree[rs]);}        Updata content specific case analysis void add_cnt (int p,int v,int t) {//tag does not affect the value of the current node, remember this tree[p]=tree[p]+1ll*v*t;                T is the interval length, and the marking needs to multiply this interval cnt[p]=cnt[p]+v; Tag update} void pushdown (int p,int l,int R) {//spike write down Pass if (!cnt[p])   Return        int mid= (L+R) >>1;    ADD_CNT (ls,cnt[p],mid-l+1), add_cnt (Rs,cnt[p],r-mid);    Tagged update cnt[p]=0;        } void Build (int p,int l,int r) {cnt[p]=0;     if (l==r) {tree[p]=val[l];        Val[i] Basic is the number of start read return;        } int mid= (L+R) >>1;        Build (Ls,l,mid), build (RS,MID+1,R);    Updata (P); } void Change (int p,int l,int r,int x,int y,int t) {//t is the tag if (x<=l&&r<=y) {add_cnt ( P,T,R-L+1);        Add Mark return;        } int mid= (L+R) >>1;    Pushdown (P,L,R);         When modifying both sides, remember to pass the mark if (x<=mid) change (ls,l,mid,x,y,t);       Access to the left son if (y>mid) change (rs,mid+1,r,x,y,t);      Access to right son Updata (p);     Remember to update} LL query (int p,int l,int r,int x,int y) {if (x<=l&&r<=y) return tree[p];        Output int mid= (L+R) directly within the range >>1;        ll Ans=0;    Pushdown (P,L,R); Pass Mark if (X<=mid) Ans=ans+query (ls,l,mid,x,y);  Access to the left son if (y>mid) ans=ans+query (rs,mid+1,r,x,y);    Access right son return ans;    }}tree;char S;int Main () {N=read (), M=read ();    for (int i=1;i<=n;i++) val[i]=read ();    Tree.build (1,1,n);        for (int i=1;i<=m;i++) {cin>>s;        int X=read (), Y=read (), Z;        if (s== ' Q ') printf ("%lld\n", Tree.query (1,1,n,x,y));    if (s== ' C ') z=read (), Tree.change (1,1,n,x,y,z); } return 0;}
2.

Description
Given a positive integer sequence A, it is required to support the following operations
1): + a B c indicates that a constant c is added to the [a, a].
2): * a b C in [A, a] a constant k.
3): Query a B queries the sum of [b].

Input
First row two positive integers n, m,n for sequence length, m for operands
The second row n positive integers, and I for the size of A[i]
The next M row, each row has and only one operation, the specific and the topic description is consistent
n,m<=100000
Other weights are <=50000

Output
For each query operation, the result of the output answer is 1000000007

Sample Input
10 10
50 14 20 18 19 11 43 43 26 44

    • 3 6 41
      QUERY 1 2
    • 5 5 14
      QUERY 1 3
      QUERY 4 4
      QUERY 2 6
    • 3 5 31
    • 4 8 20
    • 5 8 28
      QUERY 6 7

Sample Output
64
125
59
260
53200

The

is also the interval modification, the interval query, but the topic is more difficult than the above question. Why, because it needs to maintain two tags.
If it's two unrelated tags okay say, but these two tags interfere with each other!!!
Therefore, when dealing with this type of topic with multiple tags, we need to consider the effects of these tags on each other, and the order in which the tags and tags are updated successively.
If this is the case, tagging and multiplication will inevitably affect each other
if we update the markup first, then the multiply tag will become a real type, very inconvenient. So we let the multiplication mark first update, add the mark only need to multiply the previous multiplication mark, greatly reduces the implementation difficulty.
(The comment is basically not, but let the reader do the same)

#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include < Algorithm> #define INF 0x7f7f7f7fusing namespace std;typedef long long ll;typedef unsigned int ui;typedef unsigned long    Long Ull;inline int read () {int X=0,f=1;char ch=getchar (); for (;ch< ' 0 ' | |    Ch> ' 9 '; Ch=getchar ()) if (ch== '-') f=-1;    for (; ch>= ' 0 ' &&ch<= ' 9 '; Ch=getchar ()) x= (x<<1) + (x<<3) +ch-' 0 '; return x*f;}    inline void print (int x) {if (x>=10) print (X/10); Putchar (x%10+ ' 0 ');} const int N=1e5,mod=1e9+7;int n,m;struct segment{#define LS (p<<1) #define RS (p<<1|1) int tree[n*4+    10],CNT[N*4+10],RES[N*4+10],SIZE[N*4+10];    void Updata (int p) {tree[p]= (Tree[ls]+tree[rs])%mod;        void add_cnt (int p,int v) {tree[p]= (tree[p]+1ll*v*size[p])%mod;    cnt[p]= (cnt[p]+v)%mod;        } void pushdown_cnt (int p) {///spike Note the pass if (!cnt[p]) return;        ADD_CNT (Ls,cnt[p]), add_cnt (Rs,cnt[p]); Cnt[p]=0;        } void add_res (int p,int v) {tree[p]=1ll*tree[p]*v%mod;        Res[p]=1ll*res[p]*v%mod;    Cnt[p]=1ll*cnt[p]*v%mod;        } void Pushdown_res (int p) {//multiply tag next pass if (res[p]==1) return;        Add_res (Ls,res[p]), Add_res (Rs,res[p]);    Res[p]=1;    } void pushdown (int p) {pushdown_res (P), pushdown_cnt (p);}        void build (int p,int l,int r) {cnt[p]=0,res[p]=1,size[p]=r-l+1;            if (l==r) {tree[p]=read ();        Return        } int mid= (L+R) >>1;        Build (Ls,l,mid), build (RS,MID+1,R);    Updata (P); } void Change (int p,int l,int r,int x,int y,int cnt,int Res) {if (x<=l&&r<=y) {add_res (            P,res), add_cnt (p,cnt);        Return        } int mid= (L+R) >>1;        Pushdown (P);        if (x<=mid) change (ls,l,mid,x,y,cnt,res);         if (y>mid) change (rs,mid+1,r,x,y,cnt,res);    Updata (P); } int query (int p,int l,int r,int x,int y) {if (X&LT;=L&AMP;&Amp;r<=y) return tree[p];        int mid= (L+R) >>1,ans=0;        Pushdown (P);        if (x<=mid) ans= (Ans+query (ls,l,mid,x,y))%mod;        if (y>mid) ans= (Ans+query (rs,mid+1,r,x,y))%mod;    return ans;    }}tree;char S[10];int Main () {N=read (), M=read ();    Tree.build (1,1,n);        for (int i=1;i<=m;i++) {scanf ("%s", s+1);        int X=read (), Y=read (), Z;        if (s[1]== ' Q ') printf ("%d\n", Tree.query (1,1,n,x,y));        if (s[1]== ' + ') z=read (), Tree.change (1,1,n,x,y,z,1);    if (s[1]== ' * ') z=read (), Tree.change (1,1,n,x,y,0,z); } return 0;}
3. Maximum continuous sub-series and

Algorithm template--The lazy tag of line 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.