1 条题解

  • 0
    @ 2025-6-21 10:51:45

    两种修改用一个 update

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    const int MAXN = 100000;
    int n, m, mod;
    int a[MAXN + 5];
    int t[MAXN * 4 + 5];
    int lazy_add[MAXN * 4 + 5], lazy_mul[MAXN * 4 + 5];
    void down(int now, int l, int r)
    {
        int mid = (l + r) / 2;
        int add = lazy_add[now];
        int mul = lazy_mul[now];
        // 传 mul
        if (mul != 1)
        {
            t[now * 2] *= mul;
            lazy_mul[now * 2] *= mul;
            lazy_add[now * 2] *= mul;
            t[now * 2 + 1] *= mul;
            lazy_mul[now * 2 + 1] *= mul;
            lazy_add[now * 2 + 1] *= mul;
        }
        // 传 add
        if (add != 0)
        {
            t[now * 2] += (mid - l + 1) * add;
            lazy_add[now * 2] += add;
            t[now * 2 + 1] += (r - mid) * add;
            lazy_add[now * 2 + 1] += add;
        }
        // mod
        t[now * 2] %= mod;
        lazy_mul[now * 2] %= mod;
        lazy_add[now * 2] %= mod;
        t[now * 2 + 1] %= mod;
        lazy_mul[now * 2 + 1] %= mod;
        lazy_add[now * 2 + 1] %= mod;
        // clear
        lazy_add[now] = 0;
        lazy_mul[now] = 1;
    }
    void build(int now, int l, int r)
    {
        lazy_mul[now] = 1;
        lazy_add[now] = 0;
        if (l == r)
        {
            t[now] = a[l];
            return;
        }
        int mid = (l + r) / 2;
        build(now * 2, l, mid);
        build(now * 2 + 1, mid + 1, r);
        t[now] = (t[now * 2] + t[now * 2 + 1]) % mod;
    }
    void update(int now, int l, int r, int x, int y, int mul, int add)
    {
        if (x <= l && r <= y)
        {
            t[now] *= mul;
            lazy_mul[now] *= mul;
            lazy_add[now] *= mul;
            t[now] += (r - l + 1) * add;
            lazy_add[now] += add;
            t[now] %= mod;
            lazy_mul[now] %= mod;
            lazy_add[now] %= mod;
            return;
        }
        down(now, l, r);
        int mid = (l + r) / 2;
        if (x <= mid)
            update(now * 2, l, mid, x, y, mul, add);
        if (y > mid)
            update(now * 2 + 1, mid + 1, r, x, y, mul, add);
        t[now] = (t[now * 2] + t[now * 2 + 1]) % mod;
    }
    int query(int now, int l, int r, int x, int y)
    {
        if (x <= l && r <= y)
            return t[now];
        down(now, l, r);
        int mid = (l + r) / 2;
        int res = 0;
        if (x <= mid)
            res = (res + query(now * 2, l, mid, x, y)) % mod;
        if (y >= mid + 1)
            res = (res + query(now * 2 + 1, mid + 1, r, x, y)) % mod;
        return res;
    }
    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> n >> m >> mod;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        build(1, 1, n);
        for (int i = 1; i <= m; i++)
        {
            int op, x, y, z;
            cin >> op;
            if (op == 1)
            {
                cin >> x >> y >> z;
                update(1, 1, n, x, y, z, 0);
            }
            if (op == 2)
            {
                cin >> x >> y >> z;
                update(1, 1, n, x, y, 1, z);
            }
            if (op == 3)
            {
                cin >> x >> y;
                cout << query(1, 1, n, x, y) << "\n";
            }
        }
        return 0;
    }
    
    

    两个修改用两个 update

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    const int MAXN = 100000;
    int n, m, p;
    int a[MAXN + 5];
    // 线段树:单点修改、区间查询(区间和)
    int t[4 * MAXN + 5];
    int lazyAdd[4 * MAXN + 5], lazyMul[4 * MAXN + 5];
    // 基于a[]建线段树
    void build(int now, int l, int r)
    {
        lazyAdd[now] = 0;
        lazyMul[now] = 1;
        if (l == r)
        {
            t[now] = a[l];
            return;
        }
        int mid = (l + r) / 2;
        build(now * 2, l, mid);
        build(now * 2 + 1, mid + 1, r);
        t[now] = t[now * 2] + t[now * 2 + 1];
        t[now] %= p;
    }
    void down(int now, int l, int r)
    {
        int mid = (l + r) / 2;
        // 左子树 now*2,l,mid
        // 右子树 now*2+1,mid+1,r
        int add = lazyAdd[now];
        int mul = lazyMul[now];
    
        lazyMul[now * 2] *= mul;
        lazyMul[now * 2] %= p;
        lazyAdd[now * 2] *= mul;
        lazyAdd[now * 2] %= p;
        t[now * 2] *= mul;
        t[now * 2] %= p;
        lazyAdd[now * 2] += add;
        lazyAdd[now * 2] %= p;
        t[now * 2] += (mid - l + 1) * add;
        t[now * 2] %= p;
    
        lazyMul[now * 2 + 1] *= mul;
        lazyMul[now * 2 + 1] %= p;
        lazyAdd[now * 2 + 1] *= mul;
        lazyAdd[now * 2 + 1] %= p;
        t[now * 2 + 1] *= mul;
        t[now * 2 + 1] %= p;
        lazyAdd[now * 2 + 1] += add;
        lazyAdd[now * 2 + 1] %= p;
        t[now * 2 + 1] += (r - mid) * add;
        t[now * 2 + 1] %= p;
    
        lazyAdd[now] = 0;
        lazyMul[now] = 1;
    }
    // 当前做到了树上的now号节点,当前节点对应的区间为 [l,r]
    // 需要给 [x,y] 这些数都加 z
    void update_add(int now, int l, int r, int x, int y, int z)
    {
        if (x <= l && r <= y)
        {
            t[now] += (r - l + 1) * z;
            t[now] %= p;
            lazyAdd[now] += z;
            lazyAdd[now] %= p;
            return;
        }
        int mid = (l + r) / 2;
        // 左子树 now*2,l,mid
        // 右子树 now*2+1,mid+1,r
        down(now, l, r); // 把之前欠的结清
        if (x <= mid)
            update_add(now * 2, l, mid, x, y, z);
        if (y > mid)
            update_add(now * 2 + 1, mid + 1, r, x, y, z);
        t[now] = t[now * 2] + t[now * 2 + 1];
        t[now] %= p;
    }
    void update_mul(int now, int l, int r, int x, int y, int z)
    {
        if (x <= l && r <= y)
        {
            t[now] *= z;
            t[now] %= p;
            lazyMul[now] *= z;
            lazyMul[now] %= p;
            lazyAdd[now] *= z;
            lazyAdd[now] %= p;
            return;
        }
        int mid = (l + r) / 2;
        // 左子树 now*2,l,mid
        // 右子树 now*2+1,mid+1,r
        down(now, l, r); // 把之前欠的结清
        if (x <= mid)
            update_mul(now * 2, l, mid, x, y, z);
        if (y > mid)
            update_mul(now * 2 + 1, mid + 1, r, x, y, z);
        t[now] = t[now * 2] + t[now * 2 + 1];
        t[now] %= p;
    }
    int query(int now, int l, int r, int x, int y)
    {
        //[l,r] 是 [x,y] 的子区间
        if (x <= l && r <= y)
            return t[now];
        int mid = (l + r) / 2;
        // 左子树 now*2,l,mid
        // 右子树 now*2+1,mid+1,r
        down(now, l, r); // 把之前欠的结清
        int res = 0;
        if (x <= mid)
            res += query(now * 2, l, mid, x, y);
        if (y > mid)
            res += query(now * 2 + 1, mid + 1, r, x, y);
        return res % p;
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cin >> n >> m >> p;
        for (int i = 1; i <= n; i++)
        {
            cin >> a[i];
        }
        build(1, 1, n);
        while (m--)
        {
            int op, x, y, z;
            cin >> op;
            if (op == 1)
            {
                cin >> x >> y >> z;
                update_mul(1, 1, n, x, y, z);
            }
            else if (op == 2)
            {
                cin >> x >> y >> z;
                update_add(1, 1, n, x, y, z);
            }
            else if (op == 3)
            {
                cin >> x >> y; // cout sum(a[x]~a[y])
                cout << query(1, 1, n, x, y) << "\n";
            }
        }
        return 0;
    }
    
    • 1

    信息

    ID
    3617
    时间
    1000ms
    内存
    125MiB
    难度
    4
    标签
    递交数
    27
    已通过
    13
    上传者