P3373 【模板】线段树 2

令人心碎的题,尤其是pushdown操作,一定要好好想想

#include<iostream>
#include<cstdio>

using namespace std;

#define LL long long

const int N = 100010;

struct Node{
    int l, r;
    LL sum;
    LL add; // lazy1
    LL mul; // lazy2
}tr[N * 4];

int n, m, q;
LL w[N];

void pushdown(int u){
    tr[u << 1].sum = (tr[u << 1].sum * tr[u].mul + tr[u].add * (tr[u << 1].r - tr[u << 1].l + 1)) % q;
    tr[u << 1].add = (tr[u << 1].add * tr[u].mul + tr[u].add) % q;    
    tr[u << 1].mul = (tr[u << 1].mul * tr[u].mul) % q;
    
    tr[u << 1 | 1].sum = (tr[u << 1 | 1].sum * tr[u].mul + tr[u].add * (tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1)) % q;
    tr[u << 1 | 1].add = (tr[u << 1 | 1].add * tr[u].mul + tr[u].add) % q;    
    tr[u << 1 | 1].mul = (tr[u << 1 | 1].mul * tr[u].mul) % q;
    
    tr[u].mul = 1;
    tr[u].add = 0;
}

void pushup(int u){
    tr[u].sum = (tr[u << 1].sum + tr[u << 1 | 1].sum) % q;
}

void build(int u, int l, int r){
    if(l == r) tr[u] = {l, r, w[l], 0, 1};
    else{
        tr[u] = {l, r, 0, 0, 1};
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

void modify(int u, int x, LL v){
    if(tr[u].l == tr[u].r) tr[u].sum += v;
    else{
        int mid = tr[u].l + tr[u].r >> 1;
        if(x <= mid) modify(u << 1, x, v);
        else modify(u << 1 | 1, x, v);
    }
}

LL query(int u, int l, int r){
    if(l <= tr[u].l && r >= tr[u].r) return tr[u].sum;
    
    pushdown(u);
    
    int mid = tr[u].l + tr[u].r >> 1;
    LL sum = 0;
    if(l <= mid) sum = query(u << 1, l, r) % q;
    if(r > mid) sum = (sum + query(u << 1 | 1, l, r)) % q;
    return sum;
}

void change_add(int u, int l, int r, LL v){
    if(tr[u].l == l && tr[u].r == r){ // 懒就懒在这儿
        int len = r - l + 1;
        tr[u].add = (tr[u].add + v) % q;
        tr[u].sum = (tr[u].sum + len * v) % q;
        return;
    }
    
    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if(r <= mid) change_add(u << 1, l, r, v);
    else if(l > mid) change_add(u << 1 | 1, l, r, v);
    else{
        change_add(u << 1, l, mid, v);
        change_add(u << 1 | 1, mid + 1, r, v);
    }
    pushup(u);
}

void change_mul(int u, int l, int r, LL v){
    if(tr[u].l == l && tr[u].r == r){
        tr[u].add = tr[u].add * v % q;
        tr[u].mul = tr[u].mul * v % q;
        tr[u].sum = tr[u].sum * v % q;
        return;
    }
    
    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if(r <= mid) change_mul(u << 1, l, r, v);
    else if(l > mid) change_mul(u << 1 | 1, l, r, v);
    else{
        change_mul(u << 1, l, mid, v);
        change_mul(u << 1 | 1, mid + 1, r, v);
    }
    pushup(u);
}


int main(){
    cin >> n >> m >> q;
    
    for(int i = 1; i <= n; i ++) scanf("%lld", &w[i]);
    
    build(1, 1, n);
    
    while(m --){
        int k, x, y;
        LL v;
        cin >> k >> x >> y;
        
        if(k == 1){
            cin >> v;
            change_mul(1, x, y, v);
        }else if(k == 2){
            cin >> v;
            change_add(1, x, y, v);
        }else
            cout << query(1, x, y) << endl;
    }
    
    return 0;
}
原文地址:https://www.cnblogs.com/tomori/p/13762569.html