acwing1277. 维护序列(维护区间乘法、区间加法、区间和)

题意

在这里插入图片描述

思路

  1. 这题我们既要维护区间加法,又要维护区间乘法,也就是我们要维护两个懒标:add、mul。
  2. 这题给我的启发就是当我有多个懒标的时候,我们要考虑懒标之间的优先级变化。
  3. 这题为了方便懒标更新,我们应该:先更新乘懒标 mul,再更新加懒标 add。

代码

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
#define ls (k << 1)
#define rs (k << 1 | 1)
const int N = 1e5 + 10;
int n, m, p;
int a[N];
struct Tree
{
    
    
    int l, r, sum, add, mul;
} tr[N * 4];

void push_up(int k)
{
    
    
    tr[k].sum = (tr[ls].sum + tr[rs].sum) % p;
}

void cal(Tree & t, int add, int mul)
{
    
    
    t.sum = (1LL * t.sum * mul +  1LL * (t.r - t.l + 1) * add) % p;
    t.mul = 1LL * t.mul * mul % p;
    t.add = (1LL * t.add * mul + add) % p;
}

void push_down(int k)
{
    
    
    cal(tr[ls], tr[k].add, tr[k].mul);
    cal(tr[rs], tr[k].add, tr[k].mul);
    tr[k].add = 0, tr[k].mul = 1;
}

void build(int k, int l, int r)
{
    
    
    tr[k] = {
    
     l, r, 0, 0, 1};
    if (l == r)
    {
    
    
        tr[k] = {
    
     l, r, a[l], 0, 1 };
        return;
    }

    int md = (l + r) >> 1;
    build(ls, l, md);
    build(rs, md + 1, r);
    push_up(k);
}


void modify(int k, int l, int r, int add, int mul)
{
    
    
    if (tr[k].l >= l && tr[k].r <= r)
    {
    
    
        cal(tr[k], add, mul);
        return;
    }

    push_down(k);
    int md = (tr[k].l + tr[k].r) >> 1;
    if (l <= md) modify(ls, l, r, add, mul);
    if (r >  md) modify(rs, l, r, add, mul);
    push_up(k);
}

int query(int k, int l, int r)
{
    
    
    if (tr[k].l >= l && tr[k].r <= r) return tr[k].sum;

    push_down(k);
    int md = (tr[k].l + tr[k].r) >> 1;
    int sum = 0;
    if (l <= md) sum = query(ls, l, r);
    if (r >  md) sum = (sum + query(rs, l, r)) % p;
    return sum;
}


int main()
{
    
    
    scanf("%d %d", &n, &p);
    for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
    build(1, 1, n);
    scanf("%d", &m);
    int op, l, r, d;
    while (m --)
    {
    
    
        scanf("%d %d %d", &op, &l, &r);
        if (op == 1)
        {
    
    
            scanf("%d", &d);
            modify(1, l, r, 0, d);
        }
        else if (op == 2)
        {
    
    
            scanf("%d", &d);
            modify(1, l, r, d, 1);
        }
        else
        {
    
    
            printf("%d\n", query(1, l, r));
        }
    }

    return 0;
}

Guess you like

Origin blog.csdn.net/qq_34261446/article/details/121143797