题目
题目原文请移步下面的链接
- https://www.luogu.com.cn/problem/P3372
- 参考题解:https://www.luogu.com.cn/problem/solution/P3372
- 标签:
OI
、数据结构
、线段树
坑点
-
错误
CLion C++ Process finished with exit code -1073740940 (0xC0000374)
-
现象
-
Step1: 调试的时候,执行到第12行代码就会退出,最初我是用scanf读取数据,后来改成cin一样不行。
-
Step2: 后来求助老码农,帮我看看,他在mac本上执行没问题,可以正常跑,在我的windows上就挂了,后来他尝试注释掉第8行,就能正常读取数据。所以断定是第8行方法又问题。
-
Step3: 问题找到了,接下来就是我小码匠闪亮登场时间,自己挖的坑,自己还是要填了。是因为树组开销了,越界导致。
void best_coder() { int n, m; cin >> n >> m; Segment_Tree st(n); for (int i = 1; i <= n; ++i) { cin >> st.a[i]; } st.build(1, 1, n); int q, x, y; long long v; for (int i = 0; i < m; ++i) { cin >> q; if (q == 1) { cin >> x >> y >> v; st.cnt(1,x, y, v); } else { cin >> x >> y; cout << st.query(1, x, y) << endl; } } }
-
题解
思路
- 思路在这就不分享了,网络上很多,我也是看资料,边学边调试。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
struct edge {
int l, r;
LL sum, add;
};
struct Segment_Tree {
vector<edge> t;
vector<LL> a;
Segment_Tree(int n) : t(400040), a(n + 1){}
void push_up(int u) {
t[u].sum = t[u << 1].sum + t[u << 1 | 1].sum;
}
void push_down(int u) {
auto &root = t[u], &left = t[u << 1], &right = t[u << 1 | 1];
if (root.add) {
// 分析中的懒标记操作
left.add += root.add;
left.sum += (left.r - left.l + 1) * root.add;
right.add += root.add;
right.sum += (right.r - right.l + 1) * root.add;
root.add = 0;
}
}
void build(int u, int l, int r) {
t[u].l = l;
t[u].r = r;
if (l == r) {
t[u].sum = a[l];
return;
}
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
push_up(u);
}
LL query(int u, int l, int r) {
if (t[u].l >= l && t[u].r <= r) {
return t[u].sum;
}
push_down(u);
int mid = t[u].l + t[u].r >> 1;
LL s = 0;
if (l <= mid) {
s = query(u << 1, l, r);
}
if (r > mid) {
s += query(u << 1 | 1, l, r);
}
return s;
}
void modify(int u, int x, LL v) {
if (t[u].l == x && t[u].r == x) {
t[u].sum = v;
} else {
int mid = (t[u].l + t[u].r) >> 1;
if (x <= mid) {
modify(u << 1, x, v);
} else {
modify(u << 1 | 1, x, v);
}
push_up(u);
}
}
void cnt(int u, int l, int r, LL v) {
if (t[u].l >= l && t[u].r <= r) {
t[u].sum += (t[u].r - t[u].l + 1) * v;
t[u].add += v;
} else {
push_down(u);
int mid = t[u].l + t[u].r >> 1;
if (l <= mid) {
cnt(u << 1, l, r, v);
}
if (r > mid) {
cnt(u << 1 | 1, l, r, v);
}
push_up(u);
}
}
};
void best_coder() {
int n, m;
cin >> n >> m;
Segment_Tree st(n);
for (int i = 1; i <= n; ++i) {
cin >> st.a[i];
}
st.build(1, 1, n);
int q, x, y;
long long v;
for (int i = 0; i < m; ++i) {
cin >> q;
if (q == 1) {
cin >> x >> y >> v;
st.cnt(1,x, y, v);
} else {
cin >> x >> y;
cout << st.query(1, x, y) << endl;
}
}
}
void happy_coder() {
}
int main() {
// 提升cin、cout效率
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
// 小码匠
best_coder();
// 最优解
// happy_coder();
// 返回
return 0;
}
小码匠上初中后,平时作业比较多,课余时间都奉献给一方键盘和数学公式。
有时间我会把文章发布到CSDN,和更多的小伙伴分享我的学习心路。