社区讨论

求助,线段树模板写炸RE

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

讨论操作

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

当前回复
2 条
当前快照
1 份
快照标识符
@locuclel
此快照首次捕获于
2023/10/30 19:53
2 年前
此快照最后确认于
2023/11/05 06:29
2 年前
查看原帖
CPP
/*
idk wtf just happened,
but it just f**ked up.
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long L;
int n, m;
const int MAXN = 4e5 + 5, MAXM = 1e5 + 5;
int p;
struct tNode{
    L nowAns, add, mul;
}tree[MAXN];
L tmpArr[MAXM];
void buildTree(int root, int l, int r){
    tree[root].mul = 1;
    tree[root].add = 0;
    if(l == r){
        tree[root].nowAns = tmpArr[l];
        return ;
    }
    int mid = (l + r) / 2;
    buildTree(root * 2, l, mid);
    buildTree(root * 2 + 1, mid + 1, r);
    tree[root].nowAns = tree[root * 2].nowAns + tree[root * 2 + 1].nowAns;
    tree[root].nowAns %= p;
    return ;
}
void pushDown(int root, int l, int r){
    int mid = (l + r) / 2;
    tree[root * 2].nowAns = (tree[root * 2].nowAns * tree[root].mul + tree[root].add * (mid - l + 1)) % p;
    tree[root * 2 + 1].nowAns = (tree[root * 2 + 1].nowAns * tree[root].mul + tree[root].add * (r - mid)) % p;
    tree[root * 2].mul = (tree[root * 2].mul * tree[root].mul) % p;
    tree[root * 2 + 1].mul = (tree[root * 2 + 1].mul * tree[root].mul) % p;
    tree[root * 2].add = (tree[root * 2].add * tree[root].mul + tree[root].add) % p;
    tree[root * 2 + 1].add = (tree[root * 2 + 1].add * tree[root].mul + tree[root].add) % p;
    tree[root].mul = 1;
    tree[root].add = 0;
    return ;
}
void updateMul(int root, int nowl, int nowr, int l, int r, L val){
    if(r < nowl || l > nowr){
        return ;
    }
    if(l <= nowl && r <= nowr){
        tree[root].nowAns = (tree[root].nowAns * val) % p;
        tree[root].mul = (tree[root].mul * val) % p;
        tree[root].add = (tree[root].add * val) % p;
        return ;
    }
    pushDown(root, nowl, nowr);
    int mid = (nowl + nowr) / 2;
    updateMul(root * 2, nowl, mid, l, r, val);
    updateMul(root * 2 + 1, mid + 1, nowr, l, r, val);
    tree[root].nowAns = (tree[root * 2].nowAns + tree[root * 2 + 1].nowAns) % p;
    return ;
}
void updateAdd(int root, int nowl, int nowr, int l, int r, L val){
    if(r < nowl || l > nowr){
        return ;
    }
    if(l <= nowl && r <= nowr){
        tree[root].nowAns = (tree[root].nowAns + val * (nowr - nowl + 1)) % p;
        tree[root].add = (tree[root].add + val) % p;
        return ;
    }
    pushDown(root, nowl, nowr);
    int mid = (nowl + nowr) / 2;
    updateMul(root * 2, nowl, mid, l, r, val);
    updateMul(root * 2 + 1, mid + 1, nowr, l, r, val);
    tree[root].nowAns = (tree[root * 2].nowAns + tree[root * 2 + 1].nowAns) % p;
    return ;
}
L query(int root, int nowl, int nowr, int l, int r){
    if(r < nowl || l > nowr){
        return 0;
    }
    L tot = 0;
    int mid = (nowl + nowr) / 2;
    if(l <= nowl && nowr <= r){
        return tree[root].nowAns;
    }
    pushDown(root, nowl, nowr);
    if(mid >= l) tot += query(root * 2, nowl, mid, l, r) % p;
    if(mid + 1 <= r) tot += query((root * 2) | 1, mid + 1, nowr, l, r) % p;
    return tot % p;
}
int main(void){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m >> p;
    for(int i = 1; i <= n;i++){
        cin >> tmpArr[i];
    }
    buildTree(1, 1, n);
    while(m--){
        short opt;
        cin >> opt;
        int x, y;
        L val;
        /* Old way, not working.
        switch(op){
            case 1: cin >> x >> y >> val;updateMul(1, 1, n, x, y, val);break;
            case 2: cin >> x >> y >> val;updateAdd(1, 1, n, x, y, val);break;
            case 3: cin >> x >> y;cout << query(1, 1, n, x, y) << endl;break;
        }
        */
        if(opt == 1){
            cin >> x >> y >> val;
            updateMul(1, 1, n, x, y, val);
        }
        if(opt == 2){
            cin >> x >> y >> val;
            updateAdd(1, 1, n, x, y, val);
        }
        if(opt == 3){
            cin >> x >> y;
            cout << query(1, 1, n, x, y) << '\n';
        }
    }
    return 0;
}
使用GDB调试可发现在样例第六行 1 2 4 2 操作时pushDown函数陷入无限递归,调试信息如下:
CPP
Reading symbols from ./a.out...
(gdb) b 27
Breakpoint 1 at 0x1439: file LineTree2.cpp, line 27.
(gdb) r
Starting program: /mnt/c/users/255-nyancat/documents/nyancat255/a.out
5 5 38
1 5 4 2 3
2 1 4 1
3 2 5

Breakpoint 1, pushDown (root=1, l=1, r=5) at LineTree2.cpp:27
warning: Source file is more recent than executable.
27          return ;
(gdb) c
Continuing.

Breakpoint 1, pushDown (root=2, l=1, r=3) at LineTree2.cpp:27
27          return ;
(gdb) c
Continuing.

Breakpoint 1, pushDown (root=4, l=1, r=2) at LineTree2.cpp:27
27          return ;
(gdb) c
Continuing.
2 3 5 5

Breakpoint 1, pushDown (root=1, l=1, r=5) at LineTree2.cpp:27
27          return ;
(gdb) c
Continuing.

Breakpoint 1, pushDown (root=2, l=1, r=3) at LineTree2.cpp:27
27          return ;
(gdb)
Continuing.

Breakpoint 1, pushDown (root=5, l=3, r=3) at LineTree2.cpp:27
27          return ;
(gdb)
Continuing.

Breakpoint 1, pushDown (root=10, l=3, r=3) at LineTree2.cpp:27
27          return ;
(gdb)
Continuing.

Breakpoint 1, pushDown (root=20, l=3, r=3) at LineTree2.cpp:27
27          return ;
(gdb)
Continuing.

Breakpoint 1, pushDown (root=40, l=3, r=3) at LineTree2.cpp:27
27          return ;
(gdb)
Continuing.

......

Breakpoint 1, pushDown (root=327680, l=3, r=3) at LineTree2.cpp:27
27          return ;
(gdb)
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x0000000008001458 in pushDown (root=327680, l=3, r=3)
    at LineTree2.cpp:27
27          return ;
(gdb)
求助,这波是真不会了

回复

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

正在加载回复...