Segment tree template two [half reprint ..

Reprinted statement

Explanation from: https://www.luogu.org/blog/running-coder/solution-p3373
into the topic :( The following were sgt structures in the body)

This question relative to a template, added a range multiply, so the need to open up an array in a base template (multiplication lazy record mark), write functions (interval multiplied), and should mark the decentralization of functions to make lazy some modifications.

Variable Definition:
] SUM [: element segment tree node corresponding to the sum of the interval;

addv []: All elements of the segment tree node zone corresponding to the value to be added (lazy mark), all set to the initial value 0;

mulv []: All elements of the segment tree node zone corresponding to the value to be multiplied (lazy mark), all set to the initial value 1.

Process Description:
achievements (Build):
with a template. . .

Lazy mark decentralization (Push_down):
explain the principles of:

1. When performing an addition operation on a segment, since the addition of low priority, the operation does not affect the multiplication, it can be added directly;

2. When performing a multiplication operation on the range, due to the high multiplication priority, before adding operation will have an impact, it is required not only for the sum is multiplied and the multiplied mulv also requires multiplying ADDV;

3. For the foregoing reasons, it is required to re-count the multiplication operator adder.

Details of the implementation:

sum 1. subtree, mulv, addv MuLV values ​​were multiplied by the value of the current node;

2. The value of the current node mulv reduction, i.e., set to 1;

3. subtree addv addv value plus the value of the current node;

4. The sum value plus subtree (subtree contains the number of elements * addv value of the current node);

5. The current reduction value addv nodes, i.e. set to zero.

Special Note:

1. Before using the determination, if the current node is empty lazy flag without performing delegated this function. Although it will not affect the execution, but a waste of time;

2. To try to save time, to is determined on the outside of this function instead of the function.

Interval plus (Addall):
with a template. . .

By interval (Mulall):
If the current node to be fully contained within the update interval, the current node is directly modify mulv, addv, sum to a value (described with reference to decentralized function);

Otherwise, perform a similar operation to increase the interval.

Interval query (Query):
with a template. . .

Tip: Do not forget modulo. . .

Personal code

luoguP3373

#include<cstdio>
using namespace std;
#define MAX 100000+99
#define ll long long

int n,m,p;
ll sumv[MAX<<2], addv[MAX<<2], mulv[MAX<<2];
ll a[MAX];

void push_up(int o) { sumv[o] = (sumv[o<<1] + sumv[o<<1|1] ) % p;}
void build(int o, int l, int r) {
    addv[o] = 0; mulv[o] = 1;
    if(l == r) { sumv[o] = a[l]; return;}
    int mid = (l+r)>>1;
    build(o<<1, l, mid);
    build(o<<1|1, mid+1, r);
    push_up(o);
}

//void pushtag()这里的pushtag不一样,我就不写了
void push_down(int o, int l, int r) {
    if(mulv[o] != 1) {//先传mul 
        mulv[o<<1] = (mulv[o<<1] * mulv[o]) % p;
        mulv[o<<1|1] = (mulv[o<<1|1] * mulv[o]) % p;
        addv[o<<1] = (addv[o<<1] * mulv[o]) % p;
        addv[o<<1|1] = (addv[o<<1|1] * mulv[o]) % p;
        sumv[o<<1] = (sumv[o<<1] * mulv[o]) % p;
        sumv[o<<1|1] = (sumv[o<<1|1] * mulv[o]) % p;
        mulv[o] = 1;
    }
    if(addv[o]) {
        addv[o<<1] = (addv[o<<1] + addv[o]) % p;
        addv[o<<1|1] = (addv[o<<1|1] + addv[o]) % p;
        int mid = (l + r) >> 1;
        sumv[o<<1] = (sumv[o<<1] + addv[o]*(mid-l+1) ) % p;
        sumv[o<<1|1] = (sumv[o<<1|1] + addv[o]*(r-mid) ) % p ;
        addv[o] = 0;
    }
} 

void optadd(int o, int l, int r, int ql, int qr, int v) {
    if(ql <= l && r <= qr) {
        addv[o] = (ll)(addv[o] + v) % p;
        sumv[o] = (ll)(sumv[o] + v*(r-l+1) ) % p;
        return ;
    }
    push_down(o,l,r);
    int mid = (l + r) >> 1;
    if(ql <= mid) optadd(o<<1, l, mid, ql, qr, v);
    if(mid < qr) optadd(o<<1|1, mid+1, r, ql, qr, v);
    push_up(o);
}

void optmul(int o, int l, int r, int ql, int qr, int v) {
    if(ql <= l && r <= qr) {
        mulv[o] = (ll)(mulv[o] * v) % p;
        addv[o] = (ll)(addv[o] * v) % p;
        sumv[o] = (ll)(sumv[o] * v) % p;
        return ;
    }
    push_down(o,l,r);
    int mid = (l + r) >> 1;
    if(ql <= mid) optmul(o<<1, l, mid, ql, qr, v);
    if(mid < qr) optmul(o<<1|1, mid+1, r, ql, qr, v);
    push_up(o);
}

ll query(int o, int l, int r, int ql, int qr) {
    if(ql <= l && r <= qr) return (ll)sumv[o]%p;
    push_down(o,l,r);
    ll ans = 0;
    int mid = (l + r) >> 1;
    if(ql <= mid) ans = (ans + query(o<<1, l, mid, ql, qr) ) % p;
    if(mid < qr) ans = (ans + query(o<<1|1, mid+1, r, ql, qr) ) % p;
    return ans%p;
}

int main() {
    scanf("%d%d%d",&n,&m,&p);
    for(int i = 1; i <= n; i++) scanf("%lld",&a[i]);
    build(1,1,n);
    int tmp, l, r, v;
    for(int i = 1; i <= m; i++) {
        scanf("%d", &tmp);
        if(tmp == 1) { scanf("%d%d%d", &l, &r, &v); optmul(1, 1, n, l, r, v); }
        else if(tmp == 2) { scanf("%d%d%d", &l, &r, &v); optadd(1, 1, n, l, r, v); }
        else if(tmp == 3) { scanf("%d%d", &l, &r); printf("%lld\n", query(1, 1, n, l, r)); }
    }
    return 0;
}
/*
5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4
*/

Guess you like

Origin www.cnblogs.com/tyner/p/11237282.html