前言
线段树历史区间和
- 我们考虑正常线段树按顺序执行 \(m\) 次区间加操作,我们会有 \(m\) 个时刻的线段树状态。
- 这时候我们历史区间和线段数,存的值就是 \(m\) 个时刻线段树累加的结果。
- 想要维护这种结构,和直接维护,区间加,区间修改线段数的区别在于,我们需要考虑时间 \(t\)
- 我们假设在 \(x\) 时刻区间加 \([l,r]+v\),现在我们在 \(t\) 时刻 \((x\le t)\) 查询的时候,\([l,r]\) 的历史区间和是 \((t-x+1)v(r-l+1)\)
- 我们只关心当前的 \(t\),而之前的 \(x\) 我们可以拆贡献计算。于是 \((t+1)v\times len-xv\times len\)
- 这里我们对于线段树的每一个节点,记录 \(sum\) 区间和,\(hsum\) 历史区间和。
- 这是解释一下 \(sum=\sum v_i\),\(hsum=\sum -x_iv_i\),\(ans=sum\times (t+1)-hsum\) 就行了。
- 但是为了维护 \(sum,hsum\) 需要两个懒标记,\(tsum,thsum\),具体详见参考实现,其实还有矩阵写法,可我太菜了,不会啊
struct lr { int l, r; lr(int x) { l = r = x; }lr(int x, int y) { l = x; r = y; } };
namespace xds2
{
struct xdsnode { int ls, rs; uint s, hs, ts, ths; }t[N * 120];
int tim;
void newnode(int& x)
{
static int idx = 0; ++idx;
t[idx] = t[x]; x = idx;
}
void bdown(int x, uint v1, uint v2, uint len)
{
t[x].s += v1 * len; t[x].hs += v2 * len;
t[x].ts += v1; t[x].ths += v2;
}
void down(int x, int l, int r, int m)
{
if (t[x].ls || t[x].ths)
{
newnode(t[x].ls); newnode(t[x].rs);
bdown(t[x].ls, t[x].ts, t[x].ths, m - l + 1);
bdown(t[x].rs, t[x].ts, t[x].ths, r - m);
t[x].ts = t[x].ths = 0;
}
}
void up(int x)
{
t[x].s = t[t[x].ls].s + t[t[x].rs].s;
t[x].hs = t[t[x].ls].hs + t[t[x].rs].hs;
}
void upd(int& x, int l, int r, int L, int R, uint v)
{
newnode(x);
if (L <= l && r <= R)return bdown(x, v, -v * (tim - 1), r - l + 1);
int m = l + r >> 1; down(x, l, r, m);
if (L <= m)upd(t[x].ls, l, m, L, R, v);
if (R > m)upd(t[x].rs, m + 1, r, L, R, v); up(x);
}
uint ask(int x, int l, int r, int L, int R)
{
if (L <= l && r <= R)return t[x].hs + t[x].s * tim;
int m = l + r >> 1; down(x, l, r, m);
if (R <= m)return ask(t[x].ls, l, m, L, R);
if (L > m)return ask(t[x].rs, m + 1, r, L, R);
return ask(t[x].ls, l, m, L, R) + ask(t[x].rs, m + 1, r, L, R);
}
struct xds
{
int rt; uint tm;
struct xdsit
{
lr a; xds* rt;
void operator+=(uint add) { tim = rt->tm; upd(rt->rt, 1, n, a.l, a.r, add); }
operator uint() { tim = rt->tm; return ask(rt->rt, 1, n, a.l, a.r); }
};
xdsit operator[](const lr& x) { return { x,this }; }
};
}