线段树合并
const int N = ${1:this} + 5;// 总点数为 nlog(n) * Cconst int M = 4e6 + 5;
template<class Info>struct SegmentTree { int n; int idx = 0; vector<int> root; vector<int> rub; vector<Info> info; SegmentTree() : n(0) { } SegmentTree(int n_) { n = n_; root.assign(n + 1, 0); info.assign(M, Info()); }
void push_up(int p) {
}
// 千万注意 push_down 只有儿子存在的时候才加上 info[p].tag!!! void push_down(int p) { if (!info[p].tag) return; if (info[p].ls) {
} if (info[p].rs) {
} info[p].tag = 0; }
int New() { if (!rub.empty()) { int res = rub.back(); rub.pop_back(); return res; } return ++idx; }
void Del(int &p) { info[p] = Info(); rub.emplace_back(p); p = 0; }
// 调用: tr.modify(tr.root[u], x, v) // 一颗新的树直接 modify(tr.root[p], x, v) 因为 0 会自动给赋值!!! void modify(int &p, int l, int r, int x, const Info &v) { if (!p) p = New(); if (l == r) {
return; } int mid = l + r >> 1; if (x <= mid) { modify(info[p].ls, l, mid, x, v); } else { modify(info[p].rs, mid + 1, r, x, v); } push_up(p); } void modify(int &root, int x, const Info &v) { modify(root, 1, n, x, v); }
// 调用 merge(tr.root[p], tr.root[q]),把 root[q] 合并到 root[p] 里面 // 合并的时候进行一个后序遍历,可以直接把答案维护出来!!! int merge(int p, int q, int l, int r) { if (!p) {
// 记得更新再走!!!
return q; } if (!q) return p; if (l == r) {
// 先更新答案,再更新 info[q]
Del(q); return p; } int mid = l + r >> 1; info[p].ls = merge(info[p].ls, info[q].ls, l, mid); info[p].rs = merge(info[p].rs, info[q].rs, mid + 1, r); push_up(p); Del(q); return p; } void merge(int r1, int r2) { merge(r1, r2, 1, n); }
// split(tr.root[p], tr.root[q], x, y) 其中 root[q] 为 0 也没有关系!!! void split(int &p, int &q, int l, int r, int x, int y) { if (l > y || r < x) return; if (!p) return; if (x <= l && r <= y) { q = p; p = 0; return; } if (!q) q = New(); int mid = l + r >> 1; if (x <= mid) split(info[p].ls, info[q].ls, l, mid, x, y); if (mid < y) split(info[p].rs, info[q].rs, mid + 1, r, x, y); push_up(p); push_up(q); } void split(int &p, int&q, int x, int y) { split(p, q, 1, n, x, y); }
i64 query(int p, int l, int r, int x, int y) { if (l > y || r < x) return 0LL; if (!p) return 0LL; if (l >= x && r <= y) { return info[p].cnt; } int mid = l + r >> 1; i64 res = 0; res += query(info[p].ls, l, mid, x, y); res += query(info[p].rs, mid + 1, r, x, y); return res; } i64 query(int root, int x, int y) { return query(root, 1, n, x, y); }};
struct Info { int ls; int rs; int cnt; u64 val; Info() { ls = rs = val = cnt = 0; }} info;