• 线段树模板3.0 区间乘


    线段树模板3.0 区间乘

    注意lazy标记应用

    先乘后加

    int MOD;
    
    struct Tree {
        ll l, r;
        ll sum;
        ll mul, add;
    };
    
    Tree node[maxn << 2];
    int a[maxn];
    
    void push_up(int i) {
        node[i].sum = node[i << 1].sum + node[i << 1 | 1].sum;
        node[i].sum %= MOD;
    }
    
    void build(int i, int l, int r) {
        node[i].l = l;
        node[i].r = r;
        node[i].mul = 1;
        if (l == r) {
            node[i].sum = a[l] % MOD;
            return;
        }
        int mid = l + r >> 1;
        build(i << 1, l, mid);
        build(i << 1 | 1, mid + 1, r);
        push_up(i);
    }
    
    void push_down(int i) {
        node[i << 1].sum = (ll)node[i].mul * node[i << 1].sum  % MOD + ((ll)(node[i << 1].r - node[i << 1].l + 1) * node[i].add % MOD) % MOD;
        node[i << 1].sum %= MOD;
        node[i << 1 | 1].sum = (ll)node[i].mul * node[i << 1 | 1].sum % MOD + ((ll)node[i].add * (node[i << 1 | 1].r - node[i << 1 | 1].l + 1) % MOD) % MOD;
        node[i << 1 | 1].sum %= MOD;
        
        node[i << 1].mul = (ll)node[i << 1].mul * node[i].mul % MOD;
        node[i << 1 | 1].mul = (ll)node[i << 1 | 1].mul * node[i].mul % MOD;
       
        node[i << 1].add = (ll)node[i << 1].add * node[i].mul % MOD + node[i].add;
        node[i << 1].add %= MOD;
        node[i << 1 | 1].add = (ll)node[i << 1 | 1].add * node[i].mul % MOD + node[i].add;
        node[i << 1 | 1].add %= MOD;
        
        node[i].mul = 1;
        node[i].add = 0;
    }
    
    void update1(int i, int l, int r, ll val) {
        if (node[i].l > r || node[i].r < l) return;
        if (node[i].l >= l && node[i].r <= r) {
            node[i].add += val;
            node[i].add %= MOD;
            node[i].sum += val * (node[i].r - node[i].l + 1) % MOD;
            node[i].sum %= MOD;
            return;
        }
        push_down(i);
        int mid = node[i].l + node[i].r >> 1;
        if(l <= mid) update1(i << 1, l, r, val);
        if(r > mid) update1(i << 1 | 1, l, r, val);
        push_up(i);
    }
    
    void update2(int i, int l, int r, ll val) {
        if (node[i].l > r || node[i].r < l) return;
        if (node[i].l >= l && node[i].r <= r) {
            node[i].add = (ll)node[i].add * val % MOD;    //注意这里add也要乘上val
            node[i].mul = (ll)node[i].mul * val % MOD;
            node[i].sum = (ll)node[i].sum * val % MOD;
            return;
        }
        push_down(i);
        update2(i << 1, l, r, val);
        update2(i << 1 | 1, l, r, val);
        push_up(i);
    }
    
    ll query(int i, int l, int r) {
        if (node[i].l > r || node[i].r < l) return 0;
        if (node[i].l >= l && node[i].r <= r)  return node[i].sum;
        push_down(i);
        return (query(i << 1, l, r) + query(i << 1 | 1, l, r)) % MOD;
    }
    
    int main() {
        int n = readint();
        int m = readint();
        MOD = readint();
        for (int i = 1; i <= n; i++)
            a[i] = readint();
        build(1, 1, n);
        for (int i = 1; i <= m; i++) {
            int op = readint();
            if (op == 1) {
                int L = readint();
                int R = readint();
                int V = readint();
                update2(1, L, R, V);
            }
            else if (op == 2) {
                int L = readint();
                int R = readint();
                int V = readint();
                update1(1, L, R, V);
            }
            else {
                int L = readint();
                int R = readint();
                Put(query(1, L, R));
                puts("");
            }
        }
    }
    
  • 相关阅读:
    QuotationTools自动化脚本的部署和使用
    QuotationTool能做什么.
    【计算机原理】CPU部分.md
    【计算机原理】程序执行过程
    【大话存储II】学习笔记(18章),数据前处理和后处理
    【大话存储】学习笔记(17章),数据容灾
    【大话存储】学习笔记(20章),云存储
    【大话存储】学习笔记(16章),数据保护和备份技术
    【大话存储II】学习笔记(15章),NoSQL
    数据库(七),读写分离到CQRS
  • 原文地址:https://www.cnblogs.com/hznumqf/p/13834513.html
Copyright © 2020-2023  润新知