赞
踩
第一种模板只适合单点修改的题目,每次修改都传递到树的子节点。对于区间修改则不合适,同时,由于数组大小事先申明好,其点数也有上限。
class Solution { public: struct Node { int l, r; int v; }; struct Node tr[100010*4]; void build(int u, int l, int r) { tr[u] = {l, r}; if (l == r) return; int mid = (l + r) >> 1; build(u<<1, l, mid); build(u<<1|1, mid+1, r); } void modify(int u, int x, int v) { if (tr[u].l == tr[u].r) { tr[u].v = v; return; } int mid = (tr[u].l + tr[u].r) >> 1; if (x <= mid) { modify(u<<1, x, v); } else { modify(u<<1|1, x, v); } tr[u].v = max(tr[u<<1].v, tr[u<<1|1].v); } int query(int u, int l, int r) { if (l <= tr[u].l && r >= tr[u].r) { return tr[u].v; } int mid = (tr[u].l + tr[u].r) >> 1; int a = 0; int b = 0; if (l <= mid) { a = query(u<<1, l, r); } if (r > mid) { b = query(u<<1|1, l, r); } return max(a,b); } };
和第一套模板相比,增加了区间修改的功能。但是点数仍然有上限,数据量顶多十万,再往上就不能适用了。
struct Node { int l, r; int sum; int add; // 懒标记 } tr[400040]; void pushup(int u) { tr[u].sum = tr[u<<1].sum + tr[u<<1|1].sum; } void pushdown(int u) { if (tr[u].add == 0) return; auto &root = tr[u]; auto &left = tr[u<<1]; auto &right = tr[u<<1|1]; left.sum += (left.r - left.l + 1) * root.add; left.add += root.add; right.sum += (right.r - right.l + 1) * root.add; right.add += root.add; root.add = 0; } void build(int u, int l, int r) { tr[u] = {l, r}; if (l == r) { return; } int mid = (l + r) >> 1; build(u<<1, l, mid); build(u<<1|1, mid+1, r); } int query(int u, int l, int r) { if (l <= tr[u].l && r >= tr[u].r) { return tr[u].sum; } pushdown(u); int mid = (tr[u].l + tr[u].r) >> 1; int v = 0; if (l <= mid) { v = query(u<<1, l, r); } if (r > mid) { v += query(u<<1|1, l, r); } return v; } void modify(int u, int l, int r, int v) { if (l <= tr[u].l && r >= tr[u].r) { tr[u].sum += (tr[u].r - tr[u].l + 1) * v; tr[u].add += v; } else { pushdown(u); int mid = (tr[u].l + tr[u].r) >> 1; if (l <= mid) { modify(u<<1, l, r, v); } if (r > mid) { modify(u<<1|1, l, r, v); } pushup(u); } }
为了解决数据量的问题,这里提供了动态开点,解除了每个树的元素都占一个固定坑位的限制。但是仍然有限制,点数不可以随便加,有上限。
struct Node { int l; int r; int add; int val; Node() {val = add = r = l = 0;}// 这里先置零 } tr[900000]; // 申请全局变量的大小需要根据用例合理估计 int cnt = 1; void lazyCreate(int u) { if (tr[u].l == 0) tr[u].l = ++cnt; if (tr[u].r == 0) tr[u].r = ++cnt; } void pushdown(int u, int len) { if (tr[u].add == 0) return; tr[tr[u].l].add += tr[u].add; tr[tr[u].r].add += tr[u].add; tr[tr[u].l].val += (len - len / 2) * tr[u].add; tr[tr[u].r].val += len / 2 * tr[u].add; tr[u].add = 0; } void pushup(int u) { tr[u].val = tr[tr[u].l].val + tr[tr[u].r].val; } // l & r 要更新数据的范围 lc & rc 当前树节点的左右区间 void update(int u, int lc, int rc, int l, int r, int v) { if (l <= lc && r >= rc) { // 不能用 tr[u].lc tr[u].rc 此时不一定有 tr[u].val += (rc - lc + 1) * v; tr[u].add += v; return; } // 动态开点 lazyCreate(u); // 这里设置tr[u].lc. tr[u].rc pushdown(u, rc - lc + 1); // 采用len 的方式、 int mid = (lc + rc) >> 1; if (l <= mid) update(tr[u].l, lc, mid, l, r, v); if (r > mid) update(tr[u].r, mid+1, rc, l, r, v); pushup(u); } int query(int u, int lc, int rc, int l, int r) { if (l <= lc && r >= rc) { return tr[u].val; } lazyCreate(u); pushdown(u, rc - lc + 1); int mid = (lc + rc) >> 1; int v = 0; if (l <= mid) v = query(tr[u].l, lc, mid, l, r); if (r > mid) v += query(tr[u].r, mid+1, rc, l, r); return v; }
点数无限制,需要的时候申请,但是效率会很低。
struct Node { struct Node* ls; struct Node* rs; int val; // 当前节点有多少数 int add; Node() { ls = nullptr; rs = nullptr; val = 0; add = 0; } }; struct Node *root = new Node(); void pushup(struct Node* u) { u->val = u->ls->val + u->rs->val; } void pushdown(struct Node* u, int len) { if (u->ls == nullptr) { u->ls = new Node(); } if (u->rs == nullptr) { u->rs = new Node(); } if (u->add == 0) return; u->ls->add += u->add; u->ls->val += (len - len/2) * u->add; // 此时l r直接不能代表到底有多少个数, 因此需要len u->rs->add += u->add; u->rs->val += (len/2) * u->add; u->add = 0; } void modify(struct Node* u, int lc, int rc, int l, int r, int v) { if (l <= lc && r >= rc) { u->val += (rc - lc + 1) * v; u->add += v; return; } pushdown(u, rc - lc + 1); int mid = (lc + rc) / 2; if (l <= mid) modify(u->ls, lc, mid, l, r, v); if (r > mid) modify(u->rs, mid+1, rc, l, r, v); pushup(u); } int query(struct Node* u, int lc, int rc, int l, int r) { if (l <= lc && r >= rc) { return u->val; } pushdown(u, rc-lc+1); int mid = (lc + rc) / 2; int ans = 0; if (l <= mid) ans = query(u->ls, lc, mid, l, r); if (r > mid) ans += query(u->rs, mid+1, rc, l, r); return ans; }
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。