#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll MAXN = 1e5, MAXV = 1e5;
struct sec {
ll id, val, l, r, len;
sec(ll i, ll v, ll lf, ll rg, ll ln) {
id = i;
val = v;
l = lf;
r = rg;
len = ln;
}
sec() {
id = val = l = r = len = 0;
}
};
struct opr {
ll val;
opr(ll v) {
val = v;
}
opr() {
val = 0;
}
};
sec com(sec x, sec y, ll i) {
return sec(i, x.val + y.val, x.id, y.id, x.len + y.len);
}
sec com(sec x, opr y) {
return sec(x.id, x.val + y.val * x.len, x.l, x.r, x.len);
}
opr com(opr x, opr y) {
return opr(x.val + y.val);
}
sec com(sec x, ll y) {
return com(x, opr(y));
}
opr com(opr x, ll y) {
return com(x, opr(y));
}
struct segTree {
ll size, rt;
vector<sec> val;
vector<opr> tag;
void pushdown(ll x) {
tag[val[x].l] = com(tag[val[x].l], tag[x]);
val[val[x].l] = com(val[val[x].l], tag[x]);
tag[val[x].r] = com(tag[val[x].r], tag[x]);
val[val[x].r] = com(val[val[x].r], tag[x]);
tag[x] = tag[0] = opr();
val[0] = sec();
}
void pushup(ll x) {
val[x] = com(val[val[x].l], val[val[x].r], x);
}
segTree() {
val.push_back(sec());
val.push_back(sec(1, 0, 0, 0, MAXV));
tag.push_back(opr());
tag.push_back(opr());
size = MAXV;
rt = 1;
}
ll mdf(ll x, ll lx, ll rx, ll l, ll r, ll k) {
if (x == 0) {
x = val.size();
val.push_back(sec(x, 0, 0, 0, rx - lx));
tag.push_back(opr());
}
if (r <= lx || rx <= l) {
return x;
}
if (l <= lx && rx <= r) {
tag[x] = com(tag[x], k);
val[x] = com(val[x], k);
return x;
}
pushdown(x);
ll mid = (lx + rx) / 2;
ll lc = mdf(val[x].l, lx, mid, l, r, k);
val[x].l = lc;
ll rc = mdf(val[x].r, mid, rx, l, r, k);
val[x].r = rc;
pushup(x);
return x;
}
ll qry(ll x, ll lx, ll rx, ll l, ll r) {
if (x == 0) {
return sec().val;
}
if (r <= lx || rx <= l) {
return sec().val;
}
if (l <= lx && rx <= r) {
return val[x].val;
}
pushdown(x);
ll mid = (lx + rx) / 2;
return qry(val[x].l, lx, mid, l, r) + qry(val[x].r, mid, rx, l, r);
}
void out(ll x, ll lx, ll rx) {
if (x == 0) {
return;
}
cout << "val[" << x << "[" << lx << "," << rx - 1 << "]]=" << val[x].val << " " << val[x].l << " " << val[x].r << " " << val[x].len << endl;
cout << "tag[" << x << "[" << lx << "," << rx - 1 << "]]=" << tag[x].val << endl;
ll mid = (lx + rx) / 2;
out(val[x].l, lx, mid);
out(val[x].r, mid, rx);
}
} st;
ll n, q;
int main() {
cin >> n >> q;
for (ll i = 1; i <= n; i++) {
ll v;
cin >> v;
st.mdf(st.rt, 1, st.size + 1, i, i + 1, v);
}
while (q--) {
ll o, l, r, k;
cin >> o >> l >> r;
if (o == 1) {
cin >> k;
st.mdf(st.rt, 1, st.size + 1, l, r + 1, k);
} else {
cout << st.qry(st.rt, 1, st.size + 1, l, r + 1) << endl;
}
}
return 0;
}
可以AC,但是如果将代码中的
ll lc = mdf(val[x].l, lx, mid, l, r, k);
val[x].l = lc;
ll rc = mdf(val[x].r, mid, rx, l, r, k);
val[x].r = rc;
换成
val[x].l = mdf(val[x].l, lx, mid, l, r, k);
val[x].r = mdf(val[x].r, mid, rx, l, r, k);
就会7WA3RE(但是mac上下载数据测试能AC,洛谷就不行),调试发现有时候子树编号会被赋值为0,即使mdf返回的值是正确的
如果把mdf中的x换成引用:
ll mdf(ll& x, ll lx, ll rx, ll l, ll r, ll k) {
if (x == 0) {
x = val.size();
val.push_back(sec(x, 0, 0, 0, rx - lx));
tag.push_back(opr());
}
if (r <= lx || rx <= l) {
return x;
}
if (l <= lx && rx <= r) {
tag[x] = com(tag[x], k);
val[x] = com(val[x], k);
return x;
}
pushdown(x);
ll mid = (lx + rx) / 2;
mdf(val[x].l, lx, mid, l, r, k);
mdf(val[x].r, mid, rx, l, r, k);
pushup(x);
return x;
}
就是1WA3RE,调试后发现在val push_back之后上层递归中的x会莫名其妙地变成0
why?