社区讨论

30分求调,只过了1,3,4,感觉能模的地方都模了

P3373【模板】线段树 2参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@m5ffie73
此快照首次捕获于
2025/01/02 22:36
去年
此快照最后确认于
2025/11/04 12:03
4 个月前
查看原帖
CPP
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 1e5 + 10;

#define LEFT (i << 1)
#define RIGHT ((i << 1) + 1)

int n, q;
ll m, a[MAXN];
ll tree[MAXN << 2], lazy_add[MAXN << 2], lazy_mul[MAXN << 2];

void push_up(int i) {
    tree[i] = (tree[LEFT] + tree[RIGHT]) % m;
}

void push_down(int i, int l, int r) {
    if (lazy_mul[i] != 1) {
        tree[LEFT] = (tree[LEFT] * lazy_mul[i]) % m;
        tree[RIGHT] = (tree[RIGHT] * lazy_mul[i]) % m;
        lazy_mul[LEFT] = (lazy_mul[LEFT] * lazy_mul[i]) % m;
        lazy_mul[RIGHT] = (lazy_mul[RIGHT] * lazy_mul[i]) % m;
    }

    if (lazy_add[i] != 0) {
        int mid = (l + r) >> 1;
        tree[LEFT] = (tree[LEFT] + lazy_add[i] * (mid - l + 1) % m) % m;
        tree[RIGHT] = (tree[RIGHT] + lazy_add[i] * (r - mid) % m) % m;
        lazy_add[LEFT] = (lazy_add[LEFT] * lazy_mul[i] % m + lazy_add[i]) % m;
        lazy_add[RIGHT] = (lazy_add[RIGHT] * lazy_mul[i] % m + lazy_add[i]) % m;
    }

    lazy_mul[i] = 1;
    lazy_add[i] = 0;
}

void build(int i, int l, int r) {
    lazy_mul[i] = 1;
    lazy_add[i] = 0;

    if (l == r) {
        tree[i] = a[l];
        return;
    }

    int mid = (l + r) >> 1;
    build(LEFT, l, mid);
    build(RIGHT, mid + 1, r);
    push_up(i);
}

// a: *, b: +
void update(int i, int l, int r, int L, int R, ll a, ll b) {
    if (l >= L && r <= R) {
        tree[i] = (tree[i] * a) % m;
        tree[i] = (tree[i] + b * (r - l + 1) % m) % m;
        lazy_mul[i] = (lazy_mul[i] * a) % m;
        lazy_add[i] = (lazy_add[i] * a % m + b) % m;
        return;
    }

    push_down(i, l, r);

    int mid = (l + r) >> 1;
    if (mid >= L)
        update(LEFT, l, mid, L, R, a, b);
    if (mid < R)
        update(RIGHT, mid + 1, r, L, R, a, b);
    
    push_up(i);
    return;
}

ll query(int i, int l, int r, int L, int R) {
    if (l >= L && r <= R)
        return tree[i];

    push_down(i, l, r);

    int mid = (l + r) >> 1;
    ll ans = 0;
    if (mid >= L)
        ans += query(LEFT, l, mid, L, R);
    if (mid < R)
        ans += query(RIGHT, mid + 1, r, L, R);
    ans %= m;

    push_up(i);
    return ans;
}

void solve() {
    cin >> n >> q >> m;
    for (int i = 1; i <= n; i++)
        cin >> a[i];

    build(1, 1, n);

    while (q--) {
        int op, x, y;
        cin >> op >> x >> y;

        if (op == 1) {
            ll k;
            cin >> k;
            update(1, 1, n, x, y, k % m, 0);
        } else if (op == 2) {
            ll k;
            cin >> k;
            update(1, 1, n, x, y, 1, k % m);
        } else {
            ll ans = query(1, 1, n, x, y);
            cout << ans << '\n';
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    solve();
    return 0;
}

回复

2 条回复,欢迎继续交流。

正在加载回复...