可持久化的单点修改线段树,同时也是可持久化数组
Build的时候生成不超过2n个节点,每次修改生成不超过logn个节点。
MAXM是修改操作的上限。
规定Build完成的版本是1号版本。
无论是哪一种操作,都会记录一个新版本。
struct SegmentTree {
private:
#define ls lch[o]
#define rs rch[o]
static const int MAXN = 1e6 + 10;
static const int MAXM = 1e6 + 10;
int n;
int top;
int lch[MAXN * 4 + MAXM * 24];
int rch[MAXN * 4 + MAXM * 24];
ll sum[MAXN * 4 + MAXM * 24];
int cur;
int ver[MAXM];
int Clone(int o) {
++top;
sum[top] = sum[o];
lch[top] = ls;
rch[top] = rs;
return top;
}
void PushUp(int o) {
sum[o] = sum[ls] + sum[rs];
}
int BuildHelp(int l, int r) {
int o = Clone(0);
if(l == r) {
sum[o] = a[l];
ls = 0;
rs = 0;
return o;
}
int m = (l + r) >> 1;
ls = BuildHelp(l, m);
rs = BuildHelp(m + 1, r);
PushUp(o);
return o;
}
int AddHelp(int o, int l, int r, int p, ll v) {
o = Clone(o);
if(l == r) {
sum[o] += v;
return o;
}
int m = (l + r) >> 1;
if(p <= m)
ls = AddHelp(ls, l, m, p, v);
if(p >= m + 1)
rs = AddHelp(rs, m + 1, r, p, v);
PushUp(o);
return o;
}
int SetHelp(int o, int l, int r, int p, ll v) {
o = Clone(o);
if(l == r) {
sum[o] = v;
return o;
}
int m = (l + r) >> 1;
if(p <= m)
ls = SetHelp(ls, l, m, p, v);
if(p >= m + 1)
rs = SetHelp(rs, m + 1, r, p, v);
PushUp(o);
return o;
}
ll SumHelp(int o, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr)
return sum[o];
int m = (l + r) >> 1;
ll res = 0;
if(ql <= m)
res = res + SumHelp(ls, l, m, ql, qr);
if(qr >= m + 1)
res = res + SumHelp(rs, m + 1, r, ql, qr);
return res;
}
public:
void Build(int _n) {
n = _n;
cur = 0;
top = 0;
ver[cur] = BuildHelp(1, n);
}
void Add(int id, int pos, int val) {
ver[++cur] = AddHelp(ver[id], 1, n, pos, val);
}
void Set(int id, int pos, int val) {
ver[++cur] = SetHelp(ver[id], 1, n, pos, val);
}
ll Sum(int id, int lpos, int rpos) {
ll res = SumHelp(ver[id], 1, n, lpos, rpos);
ver[++cur] = ver[id];
return res;
}
} st;