线段树求助 Debug
题目描述
给你 n 个整数,请问第 x 个到第 y 个的和是多少?
在询问前后,这 n 个数中的某个区间的数可能会同时变成 z。
输入
第一行:n 和 m,表示 n 个数,m 个询问。
第二行:n 个整数。
接下来 m 行,每行3 或 4 个整数 o、x、y(、z):o 表示求和还是更改数字,如果 o=1,表示第 x 个数到第 y 个数都变成 z;如果 o = 2,表示求第 x 个到第 y 个的和。
输出
对于每次询问和,输出区间的和。
样例输入
5 3 1 2 -3 6 5 2 2 4 1 2 5 1 2 1 3
样例输出
5 3
数据范围
1<=x、y<=n;1<=o<=2;n 个数,每个数的绝对值不超过 1000;5<=n、m<=200000。
WA 40pts,代码如下:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 5;
int n, q, op, l, r, x, a[N], s[4 * N], b[4 * N];
void build(int i, int l, int r) // 建树
{
if (l == r) s[i] = a[r];
else
{
int m = l + r >> 1;
build(i << 1, l, m);
build((i << 1) + 1, m + 1, r);
s[i] = s[i << 1] + s[(i << 1) + 1];
}
}
void add(int i, int l, int r, int x, int y, int d) // 区间 [x,y] 每个数改为 d
{
if (x <= l && r <= y) s[i] = (r - l + 1) * d, b[i] = d;
else
{
int m = l + r >> 1;
if (b[i])
{
s[i << 1] = b[i] * (m - l + 1), s[(i << 1) + 1] = b[i] * (r - m);
b[i << 1] = b[i], b[(i << 1) + 1] = b[i], b[i] = 0;
}
if (x <= m) add(i << 1, l, m, x, y, d);
if (y > m) add((i << 1) + 1, m + 1, r, x, y, d);
s[i] = s[i << 1] + s[(i << 1) + 1];
}
}
int sum(int i, int l, int r, int x, int y) // 求区间 [x,y] 的和
{
if (x <= l && r <= y) return s[i];
int m = l + r >> 1, res = 0;
if (b[i])
{
s[i << 1] = b[i] * (m - l + 1), s[(i << 1) + 1] = b[i] * (r - m);
b[i << 1] = b[i], b[(i << 1) + 1] = b[i], b[i] = 0;
}
if (x <= m) res += sum(i << 1, l, m, x, y);
if (y > m) res += sum((i << 1) + 1, m + 1, r, x, y);
return res;
}
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, 1, n);
while (q--)
{
cin >> op >> l >> r;
if (op == 1)
{
cin >> x;
add(1, 1, n, l, r, x);
}
else cout << sum(1, 1, n, l, r) << "\n";
}
return 0;
}

