30分求调
查看原帖
30分求调
576807
URbit楼主2022/11/4 15:29
#include <iostream>

using std::cin;
using std::cout;
using std::endl;

class SegmentTreeR
{
#define MAXN 100100
public:
    using ull = unsigned long long;

    int arr[MAXN];
    int sum[MAXN << 2];
    int lazyAdd[MAXN << 2];
    int lazyMul[MAXN << 2];
    int p;

    void update(int k);
    void build(int k, int l, int r);
    void pushDown(int k, int l, int r);
    void changeAdd(int L, int R, int value, int k, int l, int r);
    void changeMul(int L, int R, int value, int k, int l, int r);
    ull search(int L, int R, int k, int l, int r);
};

void SegmentTreeR::update(int k)
{
    sum[k] = sum[k << 1] + sum[k << 1 | 1];
    sum[k] %= p;
}

void SegmentTreeR::build(int k, int l, int r)
{
    lazyAdd[k] = 0;
    lazyMul[k] = 1;
    if (l == r)
    {
        sum[k] = arr[l];
        sum[k] %= p;
        return;
    }

    int m = (l + r) >> 1;

    build(k << 1, l, m);
    build(k << 1 | 1, m + 1, r);

    update(k);
}

void SegmentTreeR::pushDown(int k, int l, int r)
{
    int m = (l + r) >> 1;
    int lnum = m - l + 1;
    int rnum = r - m;

    int ll = k << 1, rr = k << 1 | 1;

    sum[ll] *= lazyMul[k], sum[rr] *= lazyMul[k];
    lazyMul[ll] *= lazyMul[k], lazyMul[rr] *= lazyMul[k];
    lazyAdd[ll] *= lazyMul[k], lazyAdd[rr] *= lazyMul[k];

    sum[ll] += lazyAdd[k] * lnum, sum[rr] += lazyAdd[k] * rnum;
    lazyAdd[ll] += lazyAdd[k], lazyAdd[rr] += lazyAdd[k];

    sum[ll] %= p;
    sum[rr] %= p;
    lazyAdd[ll] %= p;
    lazyAdd[rr] %= p;
    lazyMul[ll] %= p;
    lazyMul[rr] %= p;

    lazyAdd[k] = 0;
    lazyMul[k] = 1;
}

void SegmentTreeR::changeAdd(int L, int R, int value, int k, int l, int r)
{
    if (L <= l && R >= r)
    {
        sum[k] += (r - l + 1) * value;
        lazyAdd[k] += value;
        sum[k] %= p;
        lazyAdd[k] %= p;
        return;
    }

    int m = (l + r) >> 1;
    pushDown(k, l, r);

    if (L <= m) changeAdd(L, R, value, k << 1, l, m);
    if (R > m) changeAdd(L, R, value, k << 1 | 1, m + 1, r);

    update(k);
}

void SegmentTreeR::changeMul(int L, int R, int value, int k, int l, int r)
{
    if (L <= l && R >= r)
    {
        lazyAdd[k] *= value;
        sum[k] *= value;
        lazyMul[k] *= value;
        lazyAdd[k] %= p;
        lazyMul[k] %= p;
        sum[k] %= p;
        return;
    }

    int m = (l + r) >> 1;
    pushDown(k, l, r);

    if (L <= m) changeMul(L, R, value, k << 1, l, m);
    if (R > m) changeMul(L, R, value, k << 1 | 1, m + 1, r);

    update(k);
}

SegmentTreeR::ull SegmentTreeR::search(int L, int R, int k, int l, int r)
{
    if (L <= l && R >= r)
    {
        return sum[k] % p;
    }

    int m = (l + r) >> 1;
    pushDown(k, l, r);

    ull ans = 0;
    if (L <= m) ans += search(L, R, k << 1, l, m);
    if (R > m) ans += search(L, R, k << 1 | 1, m + 1, r);
    return ans % p;
}

SegmentTreeR S;

int main()
{
    int n, m, p;
    cin >> n >> m >> p;
    S.p = p;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        S.arr[i] = x % p;
    }
    S.build(1, 1, n);
    for (int i = 0; i < m; i++)
    {
        int op, x, y, k;
        cin >> op;
        switch (op)
        {
        case 1:
            cin >> x >> y >> k;
            S.changeMul(x, y, k, 1, 1, n);
            break;
        case 2:
            cin >> x >> y >> k;
            S.changeAdd(x, y, k, 1, 1, n);
            break;
        case 3:
            cin >> x >> y;
            cout << S.search(x, y, 1, 1, n) << endl;
            break;
        }
    }
    return 0;
}
2022/11/4 15:29
加载中...