本人的实现方法是,用线段树 tr1 维护每个区间内有多少个点存在,并且记 vali 表示 [i+1,i+d] 区间内的点数,把这个东西也用线段树 tr2 维护区间和(打 lazy 标记),然后就可以统计答案了。但是实现上有一点小问题:这是主函数的内容:
if(!vis[x]){
z = tr1.ask(1, 1, n, x + 1, std::min(n, x + d));
Ans += 1ll * z * 1ll * (z - 1) / 2ll;
w = tr2.ask(1, 1, n, std::max(1, x - d), x - 1);
tr2.ask(1, 1, n, x, x);//!!!!
Ans += w;
tr2.modify(1, 1, n, std::max(1, x - d), x - 1, 1);
y = tr1.ask(1, 1, n, x + 1, std::min(n, x + d));
tr1.modify(1, 1, n, x, 1);
tr2.modify(1, 1, n, x, x, y);
vis[x] = 1;
}
else {
y = tr1.ask(1, 1, n, x + 1, std::min(n, x + d));
tr2.modify(1, 1, n, x, x, -y);
tr2.modify(1, 1, n, std::max(1, x - d), x - 1, -1);
tr1.modify(1, 1, n, x, -1);
z = tr1.ask(1, 1, n, x, std::min(n, x + d));
Ans -= 1ll * z * 1ll * (z - 1) / 2ll;
w = tr2.ask(1, 1, n, std::max(1, x - d), x);
Ans -= w;
vis[x] = 0;
}
其中带 ! 标记的语句去掉后就会 WA ,加上后就可以 AC (这句话的作用就是在 tr2 上把根到 x 的懒标记都推下去),初步推测是懒标记下传的问题,但是我想不清楚,求大佬解惑,完整代码是 代码