zoukankan      html  css  js  c++  java
  • 『线段树』线段树板子 2

    如题,已知一个数列,你需要进行下面三种操作:

    1.将某区间每一个数乘上x

    2.将某区间每一个数加上x

    3.求出某区间每一个数的和

    这道题要同时满足两个操作,,能满足这样操作的就是我们的Lazy(懒)操作了

    唯一注意的地方就是,一定要乘法在加法前进行,若加法在乘法前,那么从父亲节点向下传递的时候乘法节点就会变得很奇怪了,这样会影响我们最终的结果

    那么代码如下(草,复制粘贴销毁了我四个小时

    //#define fre yes
    
    #include <cstdio>
    #define int long long
    
    const int N = 100005;
    struct Node {
        int l, r, w;
        int addv, mul;
    } tree[N << 2];
    int MOD;
    
    void build(int k, int l, int r) {
        tree[k].l = l; tree[k].r = r; tree[k].addv = 0; tree[k].mul = 1;
        if(l == r) {
            scanf("%lld", &tree[k].w);
            tree[k].w %= MOD;
            return ;
        }
    
        int mid = (l + r) >> 1;
        build(k * 2, l, mid);
        build(k * 2 + 1, mid + 1, r);
        tree[k].w = (tree[k * 2].w + tree[k * 2 + 1].w) % MOD;
    }
    
    void pushdown(int k) {
        tree[k * 2].mul = (tree[k * 2].mul * tree[k].mul) % MOD;
        tree[k * 2 + 1].mul = (tree[k * 2 + 1].mul * tree[k].mul) % MOD;
        tree[k * 2].addv = (tree[k * 2].addv * tree[k].mul + tree[k].addv) % MOD;
        tree[k * 2 + 1].addv = (tree[k * 2 + 1].addv * tree[k].mul + tree[k].addv) % MOD;
        tree[k * 2].w = (tree[k * 2].w * tree[k].mul + (tree[k * 2].r - tree[k * 2].l + 1) * tree[k].addv) % MOD;
        tree[k * 2 + 1].w = (tree[k * 2 + 1].w * tree[k].mul + (tree[k * 2 + 1].r - tree[k * 2 + 1].l + 1) * tree[k].addv) % MOD;
        tree[k].mul = 1;
        tree[k].addv = 0;
    }
    
    void change_interval(int k, int l, int r, int x) {
        if(tree[k].l >= l && tree[k].r <= r) {
            tree[k].w = (tree[k].w + (tree[k].r - tree[k].l + 1) * x) % MOD;
            tree[k].addv = (tree[k].addv + x) % MOD;
            return ;
        }
    
        if(tree[k].addv || tree[k].mul != 1) pushdown(k);
        int mid = (tree[k].l + tree[k].r) >> 1;
        if(mid >= l) change_interval(k * 2, l, r, x);
        if(mid < r) change_interval(k * 2 + 1, l, r, x);
        tree[k].w = (tree[k * 2].w + tree[k * 2 + 1].w) % MOD;
    }
    
    void mul_interval(int k, int l, int r, int x) {
        if(tree[k].l >= l && tree[k].r <= r) {
            tree[k].w = (tree[k].w * x) % MOD;
            tree[k].addv = (tree[k].addv * x) % MOD;
            tree[k].mul = (tree[k].mul * x) % MOD;
            return ;
        }
    
        if(tree[k].addv || tree[k].mul != 1) pushdown(k);
        int mid = (tree[k].l + tree[k].r) >> 1;
        if(mid >= l) mul_interval(k * 2, l, r, x);
        if(mid < r) mul_interval(k * 2 + 1, l, r, x);
        tree[k].w = (tree[k * 2].w + tree[k * 2 + 1].w) % MOD;
    }
    
    int ans;
    void query(int k, int l, int r) {
        if(tree[k].l >= l && tree[k].r <= r) {
            ans = (ans + tree[k].w) % MOD;
            return ;
        }
    
        if(tree[k].addv || tree[k].mul != 1) pushdown(k);
        int mid = (tree[k].l + tree[k].r) >> 1;
        if(mid >= l) query(k * 2, l, r);
        if(mid < r) query(k * 2 + 1, l, r);
    }
    
    //void ask(int k) {
    //    if(tree[k].l == tree[k].r) {
    //        printf("%d ", tree[k].w);
    //        return ;
    //    }
    //
    //    if(tree[k].addv || tree[k].mul != 1) pushdown(k);
    //    int mid = (tree[k].l + tree[k].r) >> 1;
    //    ask(k * 2);
    //    ask(k * 2 + 1);
    //}
    
    signed main() {
        static int n, m;
        scanf("%lld %lld %lld", &n, &m, &MOD);
        build(1, 1, n);
        for (int i = 1; i <= m; i++) {
            int q, x, y, k;
            scanf("%lld %lld %lld", &q, &x, &y);
            if(q == 1) {
                scanf("%lld", &k);
                mul_interval(1, x, y, k);
            }
    
            if(q == 2) {
                scanf("%lld", &k);
                change_interval(1, x, y, k);
            }
    
    //        ask(1);
    //        puts("");
    
            if(q == 3) {
                ans = 0;
                query(1, x, y);
                printf("%lld
    ", ans % MOD);
            }
        } return 0;
    }
    
  • 相关阅读:
    使用Docker在本地搭建Hadoop分布式集群
    微博推荐 第三个map 源码
    对象
    http无状态(stateless)
    理解http的无连接
    http响应报文之首部行
    http响应报文之状态行
    http响应报文
    http请求报文之首部行
    http请求之请求数据
  • 原文地址:https://www.cnblogs.com/Nicoppa/p/11443818.html
Copyright © 2011-2022 走看看