Loading

线段树

线段树

P3373 【模板】线段树 2

注:本线段树使用链表形式(指针),每个结点都是左闭右闭区间。

操作为加或乘,最后答案模 \(mod\)

打两个标记,分别为 addmul

ll n, m, mod;

struct node{
    ll L, R, add, mul, sum;
    node *lc, *rc;
    void makeadd(ll k)
    {
        sum = (sum + k * (R - L + 1)) % mod;
        add = (add + k) % mod;
    }
    void makemul(ll k)
    {
        sum = (sum * k) % mod;
        mul = (mul * k) % mod;
        add = (add * k) % mod;
    }
    void pushup()
    {
        sum = (lc->sum + rc->sum) % mod;
    }
    void pushdown()
    {
        if(mul != 1)
        {
            lc->makemul(mul);
            rc->makemul(mul);
            mul = 1;
        }
        if(add)
        {
            lc->makeadd(add);
            rc->makeadd(add);
            add = 0;
        }
    }
};

const ll N = 1e5 + 4;
ll a[N];

void Build(node *now, ll l, ll r)
{
    now->L = l;
    now->R = r;
    now->add = 0;
    now->mul = 1;
    now->sum = 0;
    if(l < r)
    {
        ll mid = (l + r) >> 1;
        now->lc = new node;
        now->rc = new node;
        Build(now->lc, l, mid);
        Build(now->rc, mid + 1, r);
        now->pushup();
    }
    else
    {
        now->sum = a[l];
        now->lc = now->rc = NULL;
    }
}

ll check(node *now, ll l, ll r)
{
    if(l <= now->L and now->R <= r)
        return now->sum % mod;
    now->pushdown();
    ll mid = (now->L + now->R) >> 1;
    ll ans = 0;
    if(l <= mid)
        ans = (ans + check(now->lc, l, r)) % mod;
    if(mid < r)
        ans = (ans + check(now->rc, l , r)) % mod;
    return ans % mod;
}

void add(node *now, ll l, ll r, ll k)
{
    if(l <= now->L and now->R <= r)
        now->makeadd(k);
    else
    {
        now->pushdown();
        ll mid = (now->L + now->R) >> 1;
        if(l <= mid)
            add(now->lc, l, r, k);
        if(mid < r)
            add(now->rc, l, r, k);
        now->pushup();
    }
}

void mul(node *now, ll l, ll r, ll k)
{
    if(l <= now->L and now->R <= r)
        now->makemul(k);
    else
    {
        now->pushdown();
        ll mid = (now->L + now->R) >> 1;
        if(l <= mid)
            mul(now->lc, l, r, k);
        if(mid < r)
            mul(now->rc, l, r, k);
        now->pushup();
    }
}

int main()
{
    n = read(), m = read(), mod = read();
    for(int i = 1; i <= n; ++i)
        a[i] = read();
    node *root;
    root = new node;
    Build(root, 1, n);
    for(int i = 1; i <= m; ++i)
    {
        ll opt = read(), l = read(), r = read(), k;
        if(opt == 1)
        {
            k = read();
            mul(root, l, r, k);
        }
        if(opt == 2)
        {
            k = read();
            add(root, l ,r, k);
        }
        if(opt == 3)
        {
            printf("%lld\n", check(root, l, r) % mod);
        }
    }
    return 0;
}
posted @ 2021-09-08 19:02  EdisonBa  阅读(64)  评论(2编辑  收藏  举报