但是当我把 solve 写成这样:
void solve(int zyl, int zyr, int ql, int qr) {
if (ql > qr) return;
if (zyl == zyr) {
for (int i = ql; i <= qr; ++i) {
ans[q[i].id] = zyl;
}
return;
}
int mid = (zyl + zyr) / 2, t1t = 0, t2t = 0, midv = val[mid];
vector<pair<int, int>> upds;
for (int i = ql; i <= qr; ++i) {
if (q[i].opt == 1) {
if (q[i].r <= midv) {
update(q[i].l, q[i].k);
upds.push_back({q[i].l, q[i].k});
t1[++t1t] = q[i];
}
else t2[++t2t] = q[i];
} else {
int tmp = query(q[i].r) - query(q[i].l - 1);
if (q[i].k <= tmp) t1[++t1t] = q[i];
else /*q[i].k -= tmp, */t2[++t2t] = q[i];
}
}
int qcnt = ql - 1;
for (int i = 1; i <= t1t; ++i) q[++qcnt] = t1[i];
for (int i = 1; i <= t2t; ++i) q[++qcnt] = t2[i];
solve(mid + 1, zyr, ql + t1t, qr);
for (auto i : upds) update(i.first, -i.second);
solve(zyl, mid, ql, ql + t1t - 1);
}
就不会过。我的想法就是这个更新毕竟只会影响到 [ql+tt1,qr] 的询问,并不会影响到 [ql,ql+t1t−1] 的询问,所以就可以先把要影响到的区间处理了再消除贡献。
但是这种思路是可以过 P1527 的,我 P1527 的代码是这样的。
所以为什么同样的思路两个题目一个正确一个错误,这两道题目是有什么实质性的区别而导致分治的时候需要格外注意某一点?