社区讨论
求助,线段树模板写炸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调试可发现在样例第六行
CPP1 2 4 2
操作时pushDown函数陷入无限递归,调试信息如下: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 条回复,欢迎继续交流。
正在加载回复...