蒟蒻对于线段树的一点疑惑

P1253 扶苏的问题

bunashengyibugaiming @ 2023-11-16 18:04:50

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int inf  = -1e18;
struct Node {
    int l = 0, r = 0;
    int lj = 0, lg = 0;
    int pre = 0;
} t[40000005];
int n, q;
int a[10000005];
inline int ls(int p) { return p << 1; }
inline int rs(int p) { return p << 1 | 1; }
void push_up(int p) { t[p].pre = max(t[ls(p)].pre, t[rs(p)].pre); }
void build(int l, int r, int p) {
    t[p].l = l;
    t[p].r = r;
    if (l == r) {
        t[p].lg  = inf;
        t[p].lj  = 0;
        t[p].pre = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, ls(p));
    build(mid + 1, r, rs(p));
    t[p].lg = inf;
    push_up(p);
}
void push_down(int p) {
    if (t[p].lg != inf) {
        t[ls(p)].lg  = t[p].lg;
        t[rs(p)].lg  = t[p].lg;
        t[ls(p)].pre = t[p].lg;
        t[rs(p)].pre = t[p].lg;
        t[ls(p)].lj  = 0;
        t[rs(p)].lj  = 0;
        t[p].lg      = inf;
    }
    if (t[p].lj != 0) {
        t[ls(p)].lj += t[p].lj;
        t[rs(p)].lj += t[p].lj;
        t[ls(p)].pre += t[p].lj;
        t[rs(p)].pre += t[p].lj;
        t[p].lj = 0;
    }
}
void modify_j(int l, int r, int p, int pre) {
    if (l <= t[p].l && t[p].r <= r) {
        push_down(p);
        t[p].pre += pre;
        t[p].lj += pre;
        return;
    }
    push_down(p);
    int mid = (t[p].l + t[p].r) >> 1;
    if (l <= mid) {
        modify_j(l, r, ls(p), pre);
    }
    if (r > mid) {
        modify_j(l, r, rs(p), pre);
    }
    push_up(p);
    return;
}
int query(int l, int r, int p) {
    if (l <= t[p].l && r >= t[p].r) {
        return t[p].pre;
    }
    push_down(p);
    int mid = (t[p].l + t[p].r) >> 1;
    int ans = inf;
    if (l <= mid) {
        ans = max(ans, query(l, r, ls(p)));
    }
    if (r > mid) {
        ans = max(ans, query(l, r, rs(p)));
    }
    return ans;
}
void modify_g(int l, int r, int p, int pre) {
    if (l <= t[p].l && t[p].r <= r) {
        t[p].pre = pre;
        t[p].lg  = pre;
        t[p].lj  = 0;
        return;
    }
    push_down(p);
    int mid = (t[p].l + t[p].r) >> 1;
    if (l <= mid) {
        modify_g(l, r, ls(p), pre);
    }
    if (r > mid) {
        modify_g(l, r, rs(p), pre);
    }
    push_up(p);
    return;
}
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> q;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    build(1, n, 1);
    while (q--) {
        int op, l, r, x;
        cin >> op;
        if (op == 1) {
            cin >> l >> r >> x;
            modify_g(l, r, 1, x);
        }
        if (op == 2) {
            cin >> l >> r >> x;
            modify_j(l, r, 1, x);
        }
        if (op == 3) {
            cin >> l >> r;
            cout << query(l, r, 1) << endl;
        }
    }
    return 0;
}

这个代码在t数组开成4e6+5,a数组开成1e6+5时最后一个点会RE

评测记录

但将t数组开成4e7+5,a数组开成1e7+5时可以通过

评测记录

同机房dalao说是因为第50行的代码导致我的线段树要开8倍空间,

而另一位dalao用差不多的代码开4倍空间通过了。

这是另一位dalao的代码

蒟蒻不太明白为什么会导致开到8倍空间,救救蒟蒻qwq


by YQsunny @ 2023-11-16 18:06:34

if (l <= t[p].l && t[p].r <= r) {
        push_down(p);
        t[p].pre += pre;
        t[p].lj += pre;
        return;
    }

@bunashengyibugaiming

在跳到叶子节点时也会进行push—down操作,就要多用空间


by bunashengyibugaiming @ 2023-11-16 18:08:11

@YQsunny Orz感谢大佬,蒟蒻懂了,但是为啥另一个大佬也是这样写的没有出问题啊


by bunashengyibugaiming @ 2023-11-16 18:14:26

@bunashengyibugaiming 破案了,另一位大佬将t数组建立在了最后导致就算数组越界也不会访问到别的值,而我将t数组定义在了前面,会导致访问到别的值


by bunashengyibugaiming @ 2023-11-16 18:14:57

此贴结


by YQsunny @ 2023-11-16 18:15:57

@bunashengyibugaiming

我不知道,但是你知道你的为啥出错下次别这么写就行了。。。


|