Line segment tree (4) - Yang Ziyue algorithm

Line segment tree (4) - Yang Ziyue algorithm

Portal: Line Segment Tree (3)


Oh, now is the last big boss of the line segment tree template question, that is, the update is the interval, the question is also the interval, it looks disgusting, now solve it! (We put add(lazy) and sum in a struct, so we can see clearly)


First of all, he asked about the interval sum, So, it must be built at the beginning, not much to say:

void build(int l,int r,int nod){
    tree[nod].add = 0;
    if (l==r){
        tree[nod].sum=a[l];
        return;
    }
    int mid=(l+r)/2;
    build(l,mid,nod*2);
    build(mid+1,r,nod*2+1);
    tree[nod].sum=tree[nod*2].sum+tree[nod*2+1].sum;
}

Looking at update, this must be optimized with lazy, that is, the interval is matched, but when updating sum, you must pay attention to the interval when the interval is matched, and each element in this interval must be added with v, So, tree[nod]. Sum+=(r-l+1)*v to
see update:

void update(int l,int r,int ll,int rr,int v,int nod){
    if (l==ll &&r==rr){
        tree[nod].sum+=(r-l+1)*v;
        tree[nod].add+=v;
        return;
    }
    pushdown(nod, l, r);
    int mid=(l+r)/2;
    if (rr<=mid) update(l,mid,ll,rr,v,nod*2);
    else if (ll>=mid+1) update(mid+1,r,ll,rr,v,nod*2+1); 
    else {
        update(l,mid,ll,mid,v,nod*2);
        update(mid+1,r,mid+1,rr,v,nod*2+1);
    }
    pushup(nod);
}

Here is a small question how to write pushdown, the witty boss will definitely write it, but I have to say, this add means to add it to every number in this interval, it is calculating the sum of the left and right sons When , multiply the corresponding number of elements in the son interval (this is why pushdown needs to pass l and r)

void pushdown(int nod, int l, int r) {
    int mid = (l+r)/2;
    tree[nod*2].sum+=(mid-l+1)*tree[nod].add;
    tree[nod*2+1].sum+=(r-mid)*tree[nod].add;
    tree[nod*2].add+=tree[nod].add;
    tree[nod*2+1].add+=tree[nod].add;
    tree[nod].add=0;
}

There is a small question, how to write pushup? The sum must be pushed up, what about add? Of couse NOT! First of all, add itself records the amount of change of its son, and then, when you push up, your add is 0, so what the hell are you pushing?

void pushup(int nod) {
    tree[nod].sum = tree[nod*2].sum + tree[nod*2+1].sum;
}

After this is done, the solve is simple, and the original is exactly the same:

int solve(int l,int r,int ll,int rr,int nod){
    if (l==ll &&r==rr){
        return tree[nod].sum;
    }
    pushdown(nod, l, r);
    int mid=(l+r)/2;
    if (rr<=mid) return solve(l,mid,ll,rr,nod*2);
    else if(ll>=mid+1) return solve(mid+1,r,ll,rr,nod*2+1);
    else return solve(l,mid,ll,mid,nod*2)+solve(mid+1,r,mid+1,rr,nod*2+1);
}

OK! Done


Long-winded:
If you have no problem with the line segment tree so far, Congratulations! - You finally understand the fur of the line segment tree. Of course, the use of the line segment tree is definitely not only to find min, find max, and find sum, it was also said that the line segment tree can solve all interval problems. Correspondingly, the interval information recorded in the line segment tree is different.

Look at the question:
give a sequence of length n (n<=200000), and then give m operations. For each operation, first give a k, if k=1, then input x, y, and output the interval [ The number of numbers divisible by 7 in x, y] , if k=2, enter x, y, z, add z to each element of the interval [x, y]

Well, I've been tired of writing line segment trees recently, and I don't know when I'll come out with line segment trees (5), so I'll tell you this question later!
OK, 88

Reproduction is strictly prohibited without the author's permission:

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324695564&siteId=291194637