P3373 【模板】線段樹 2(區間加法+區間乘法+區間求和取模)

#include <bits/stdc++.h>
#define lson l,m,rt << 1
#define rson m+1,r,rt << 1|1
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
int mod = 1000;
ll sum[maxn << 2];
ll add[maxn << 2];
ll mul[maxn << 2];
struct Node {
    ll l,r;
    ll mid() {
        return (l + r) >> 1;
    }
} tree[maxn << 2];
void PushUp(ll rt) {
    sum[rt] = (sum[rt << 1] + sum[rt << 1|1]) % mod;
}

void PushDown(ll rt,ll len) {
    sum[rt << 1]=(sum[rt << 1]*mul[rt]+add[rt]*(len - len/2)) % mod;
    sum[rt << 1|1]=(sum[rt << 1|1]*mul[rt]+add[rt]*(len/2)) % mod;
    mul[rt << 1]=(mul[rt << 1]*mul[rt]) % mod;
    mul[rt << 1|1]=(mul[rt << 1|1]*mul[rt]) % mod;
    add[rt << 1]=(add[rt << 1]*mul[rt]+add[rt]) % mod;
    add[rt << 1|1]=(add[rt << 1|1]*mul[rt]+add[rt]) % mod;
    mul[rt] = 1;
    add[rt] = 0;
}

void BuildTree(ll l,ll r,ll rt) {
    tree[rt].l = l;
    tree[rt].r = r;
    if(l == r) {
        cin >> sum[rt];
        sum[rt] %= mod;
        return ;
    }

    ll m = tree[rt].mid();
    BuildTree(lson);
    BuildTree(rson);
    PushUp(rt);
}

void Updata_add(ll c,ll l,ll r,ll rt) {
    if(tree[rt].l ==l && tree[rt].r == r) {
        add[rt] = (add[rt] + c) % mod;
        sum[rt] = (sum[rt] + (ll) c * (r - l + 1)) % mod;
        return ;
    }

    PushDown(rt,tree[rt].r - tree[rt].l + 1);

    ll m = tree[rt].mid();
    if(r <= m)
        Updata_add(c,l,r,rt << 1);
    else if(l > m)
        Updata_add(c,l,r,rt << 1|1);
    else {
        Updata_add(c,lson);
        Updata_add(c,rson);
    }
    PushUp(rt);
}

void Updata_mul(ll c,ll l,ll r,ll rt) {
    if(tree[rt].l == l && tree[rt].r == r) {
        sum[rt] = (sum[rt]*c) % mod;
        mul[rt] = (mul[rt]*c) % mod;
        add[rt] = (add[rt]*c) % mod;
        return ;
    }

    PushDown(rt,tree[rt].r - tree[rt].l + 1);
    ll m = tree[rt].mid();
    if(r <= m)
        Updata_mul(c,l,r,rt << 1);
    else if(l > m)
        Updata_mul(c,l,r,rt << 1|1);
    else {
        Updata_mul(c,lson);
        Updata_mul(c,rson);
    }
    PushUp(rt);
}

ll Query(ll l,ll r,ll rt) {
    if(tree[rt].l == l && tree[rt].r == r) {
        return sum[rt];
    }

    ll m = tree[rt].mid();
    ll res = 0;
    PushDown(rt,tree[rt].r - tree[rt].l + 1);
    if(r <= m)
        res = (res + Query(l,r,rt << 1))% mod;
    else if(l > m)
        res = (res + Query(l,r,rt << 1|1))% mod;
    else
        res = (res + Query(lson) + Query(rson)) % mod;
    return res;
}

int main() {
    ll n,m,T;
    while(cin >> n >> m >> mod) {
        memset(sum,0,sizeof(sum));
        memset(add,0,sizeof(add));
        for(ll i = 0; i <= n*4; i++)
            mul[i] = 1;
        BuildTree(1,n,1);
        while(m--) {
            ll op,x,y,k;
            cin >> op;
            if(op == 1) {
                cin >> x >> y >> k;
                Updata_mul(k,x,y,1);
            } else if(op == 2) {
                cin >> x >> y >> k;
                Updata_add(k,x,y,1);
            } else {
                cin >> x >> y;
                printf("%lld\n",Query(x,y,1));
            }
        }
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章