Typed_SIGTERM @ 2024-10-26 08:36:50
输出 11 8 16
,不知道哪里错了 /kk
#include <iostream>
using namespace std;
namespace Solution {
using LL = long long;
constexpr int N = 1e5 + 5, NODE = N << 2; // 线段树是完全二叉树,节点数 < 深度 * 4
int n;
LL a[N], tree[NODE], flag[NODE];
void dbg() {
cerr << "tree: ";
for (int i = 1; i < n * 2; ++i) cerr << tree[i] << ' ';
cerr << "\nflag: ";
for (int i = 1; i < n * 2; ++i) cerr << flag[i] << ' ';
cerr << '\n';
}
inline int left(int x) { return x << 1; }
inline int right(int x) { return (x << 1) + 1; }
void pushDown(int root, int l, int r) {
cerr << "push " << root << ' ' << l << ' ' << r << '\n';
if (!flag[root]) return;
tree[root] += flag[root] * (r - l + 1); // [l, r] 区间内都加了 flag[root]
if (l != r) { // 需要下发标记
flag[left(root)] += flag[root];
flag[right(root)] += flag[root];
}
flag[root] = 0;
}
inline void pushUp(int x) {
tree[x] = tree[left(x)] + tree[right(x)];
}
void build(int root, int l, int r) {
if (l == r) {
tree[root] = a[l];
} else {
int mid = (l + r) >> 1;
build(left(root), l, mid);
build(right(root), mid + 1, r);
pushUp(root);
}
}
void update(int l, int r, LL value, int root = 1, int start = 1, int end = n) {
cerr << "update " << l << '~' << r << ", " << value << ", " << root << ", " << start << '~' << end << '\n';
if (l <= start && r >= end) {
// @todo optimize
tree[root] += value * (end - start + 1);
flag[root] += value;
} else {
pushDown(root, start, end);
int mid = (start + end) >> 1;
if (l <= mid)
update(l, r, value, left(root), start, mid);
if (r > mid)
update(l, r, value, right(root), mid + 1, end);
pushUp(root);
}
dbg();
}
LL query(int l, int r, int root = 1, int start = 1, int end = n) {
cerr << "query\n";
if (l <= start && r >= end) return tree[root];
pushDown(root, start, end);
if (start == end) return tree[root];
int ans = 0, mid = (start + end) >> 1;
if (l <= mid) ans += query(l, r, left(root), start, mid);
if (r > mid) ans += query(l, r, right(root), mid + 1, end);
dbg();
return ans;
}
void solve() {
int m;
cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> a[i];
build(1, 1, n);
while (m--) {
int op, x, y, k;
cin >> op >> x >> y;
switch (op) {
case 1:
cin >> k;
update(x, y, k);
break;
case 2:
cout << query(x, y) << '\n';
break;
}
cerr << '\n';
}
}
} // namespace Solution
int main() {
ios::sync_with_stdio(0);
cin.tie(nullptr);
Solution::solve();
return 0;
}
(祝各位 CSP 2024 rp++)
by __Louis__ @ 2024-10-26 08:40:20
query 哪里出问题了,因该不需要特判l==r
by __Louis__ @ 2024-10-26 08:42:11
还有一点,下发标记了以后就要更新值,否则更新会慢。
建议写 add_tag 函数。
@ZihanHu
by __Louis__ @ 2024-10-26 08:46:22
void add_tag(int x,int l,int r,int tg){
tree[x].da+=(r-l+1)*tg;
tree[x].tg+=tg;
}
void push_down(int x,int l,int r){
if(tree[x].tg){
int mid=(l+r)>>1;
add_tag(ls(x),l,mid,tree[x].tg);
add_tag(rs(x),mid+1,r,tree[x].tg);
tree[x].tg=0;
}
}
这是我平时写 push_down 时候的写法,加了 tag 以后要及时更新值,否则会出问题。
by Typed_SIGTERM @ 2024-10-26 08:53:56
@Louis 感谢大佬,祝您 CSP rp++
现在有 10pts 了!
(看了一下第一个点的数据,又是最后一个查询寄了 xwx
8 10
640 591 141 307 942 58 775 133
2 1 5
2 3 8
2 3 6
2 5 8
2 4 8
1 4 8 60
2 1 6
2 5 8
1 3 7 15
1 2 6 86
ans:
2621
2356
1448
1908
2215
2859
2388