• [Luogu] 线段树 2


    https://www.luogu.org/problemnew/show/P3373

    双懒标记下放

    先乘后加

    #include <bits/stdc++.h>
    
    using namespace std;
    const int N = 1e5 + 10;
    
    #define LL long long
    #define lson jd << 1
    #define rson jd << 1 | 1
    
    LL w[N << 2], size[N << 2], fadd[N << 2], fmul[N << 2], Answer;
    int n, Ty, Mod;
    
    #define gc getchar()
    
    inline int read() {
        int x = 0; char c = gc;
        while(c < '0' || c > '9') c = gc;
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
        return x;
    } 
    
    void Build_tree(int l, int r, int jd) {
        size[jd] = (r - l + 1); fmul[jd] = 1;
        if(l == r) {w[jd] = read(); w[jd] %= Mod; return ;}
        int mid = (l + r) >> 1;
        Build_tree(l, mid, lson);
        Build_tree(mid + 1, r, rson);
        w[jd] = (w[lson] + w[rson]) % Mod;
    }
    
    void Down(int jd) {
        if(!fadd[jd] && fmul[jd] == 1) return ;
        w[lson] = w[lson] * fmul[jd] % Mod;
        w[rson] = w[rson] * fmul[jd] % Mod;
        w[lson] = w[lson] + fadd[jd] * size[lson] % Mod;
        w[rson] = w[rson] + fadd[jd] * size[rson] % Mod;
        fadd[lson] = (fadd[lson] * fmul[jd] + fadd[jd]) % Mod;
        fadd[rson] = (fadd[rson] * fmul[jd] + fadd[jd]) % Mod;
        fmul[lson] = fmul[lson] * fmul[jd] % Mod;
        fmul[rson] = fmul[rson] * fmul[jd] % Mod;
        fadd[jd] = 0;
        fmul[jd] = 1;
    }
    
    void Sec_G_mul(int l, int r, int jd, int x, int y, int imp) {
        if(x <= l && r <= y) {
            w[jd] = (w[jd] * imp) % Mod;
            fmul[jd] = (fmul[jd] * imp) % Mod;
            fadd[jd] = (fadd[jd] * imp) % Mod;
            return ;
        }
        Down(jd); 
        int mid = (l + r) >> 1;
        if(x <= mid) Sec_G_mul(l, mid, lson, x, y, imp);
        if(y > mid)  Sec_G_mul(mid + 1, r, rson, x, y, imp);
        w[jd] = (w[lson] + w[rson]) % Mod;
    }
    
    void Sec_G_add(int l, int r, int jd, int x, int y, int k) {
        if(x <= l && r <= y) {
            w[jd] = (w[jd] + size[jd] * k) % Mod;
            fadd[jd] = (fadd[jd] + k) % Mod;
            return ;
        }
        Down(jd);
        int mid = (l + r) >> 1;
        if(x <= mid) Sec_G_add(l, mid, lson, x, y, k);
        if(y > mid)  Sec_G_add(mid + 1, r, rson, x, y, k);
        w[jd] = (w[lson] + w[rson]) % Mod; 
    }
    
    void Sec_A(int l, int r, int jd, int x, int y) {
        if(x <= l && r <= y) {
            Answer += w[jd];
            if(Answer >= Mod) Answer %= Mod;
            return ;
        }
        Down(jd);
        int mid = (l + r) >> 1;
        if(x <= mid) Sec_A(l, mid, lson, x, y);
        if(y > mid)  Sec_A(mid + 1, r, rson, x, y);
    } 
    
    int main() {
        n = read();
        Ty = read();
        Mod = read();
        Build_tree(1, n, 1);
        while(Ty --) {
            int opt = read();
            if(opt == 1) {
                int x = read(), y = read(), k = read(); k %= Mod;
                Sec_G_mul(1, n, 1, x, y, k);
            } else if(opt == 2) {
                int x = read(), y = read(), k = read(); k %= Mod;
                Sec_G_add(1, n, 1, x, y, k); 
            } else {
                int x = read(), y = read();
                Answer = 0;
                Sec_A(1, n, 1, x, y);
                cout << Answer << endl; 
            }
        }    
        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
    */

     乘法标记下放的时候,加法标记也应该进行改变

    这样的话,在标记下放时,先放乘法后放加法。

  • 相关阅读:
    20220420 08:00:02
    20220417 08:00:02
    20220422 08:00:01
    20220416 08:00:01
    20220415 08:00:01
    20220424 08:00:01
    20220421 08:00:01
    20220423 08:00:01
    【MQ】java 从零开始实现消息队列 mq02如何实现生产者调用消费者?
    【mq】从零开始实现 mq01生产者、消费者启动
  • 原文地址:https://www.cnblogs.com/shandongs1/p/8503015.html
Copyright © 2020-2023  润新知