线段树模板(区间加/乘)

https://www.luogu.org/problemnew/show/P3373
如题,已知一个数列,你需要进行下面三种操作:
1.将某区间每一个数乘上x
2.将某区间每一个数加上x
3.求出某区间每一个数的和

#include<bits/stdc++.h>
#optimaze
using namespace std;
typedef long long ll;

const int maxn = 100000 + 5;
ll tre[maxn << 2], lzyadd[maxn << 2], lzymup[maxn << 2];
int x, n, m, p;
void push_up(int rt) {
    tre[rt] = (tre[rt << 1] + tre[rt << 1 | 1]) % p;
}
void push_down(int rt, int l, int r) {
    if(lzyadd[rt] == 0 && lzymup[rt] == 1) return;
    int mid = l + r >> 1;
    tre[rt << 1] = (tre[rt << 1] * lzymup[rt] + (mid - l + 1) * lzyadd[rt]) % p;
    tre[rt << 1 | 1] = (tre[rt << 1 | 1] * lzymup[rt] + (r - mid) * lzyadd[rt]) % p;
    lzymup[rt << 1] = lzymup[rt << 1] * lzymup[rt] % p;
    lzymup[rt << 1 | 1] = lzymup[rt << 1 | 1] * lzymup[rt] % p;
    lzyadd[rt << 1] = (lzyadd[rt << 1] * lzymup[rt] + lzyadd[rt]) % p;
    lzyadd[rt << 1 | 1] = (lzyadd[rt << 1 | 1] * lzymup[rt] + lzyadd[rt]) % p;
    lzyadd[rt] = 0;
    lzymup[rt] = 1;
    return;
}
void build(int rt, int l, int r) {
    lzyadd[rt] = 0;
    lzymup[rt] = 1;
    if(l == r) {
        cin >> tre[rt];
        tre[rt] = tre[rt] % p;
        return;
    }
    int mid = l + r >> 1;
    build(rt << 1, l, mid);
    build(rt << 1 | 1, mid + 1, r);
    push_up(rt);
}
void update(int rt, int l, int r, int L, int R, bool op, int x) {
    if(L <= l && r <= R) {
        if(op) {
            tre[rt] = tre[rt] * x % p;
            lzymup[rt] = lzymup[rt] * x % p;
            lzyadd[rt] = lzyadd[rt] * x % p;
        }
        else {
            lzyadd[rt] = (lzyadd[rt] + x) % p;
            tre[rt] = (tre[rt] + (r - l + 1) * x) % p;
        }
        return;
    }
    push_down(rt, l, r);
    int mid = l + r >> 1;
    if(L <= mid) update(rt << 1, l, mid, L, R, op, x);
    if(mid < R) update(rt << 1 | 1, mid + 1, r, L, R, op, x);
    push_up(rt);
}
ll query(int rt, int l, int r, int L, int R) {
    if(L <= l && r <= R) return tre[rt];
    push_down(rt, l, r);
    int mid = l + r >> 1;
    ll res = 0;
    if(L <= mid) res = (res % p + query(rt << 1, l, mid, L, R) % p) % p;
    if(R > mid) res = (res % p + query(rt << 1 | 1, mid + 1, r, L, R) % p) % p;
    push_up(rt);
    return res;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m >> p;
    build(1, 1, n);
    int op, x, y, z;
    while(m--) {
        cin >> op;
        if(op == 1) {
            cin >> x >> y >> z;
            update(1, 1, n, x, y, 1, z);
        }
        else if(op == 2) {
            cin >> x >> y >> z;
            update(1, 1, n, x, y, 0, z);
        }
        else if(op == 3) {
            cin >> x >> y;
            cout << query(1, 1, n, x, y) << endl;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_40588429/article/details/84714525