动态开点线段树

template<typename T>
struct Node {
  int l, r;
  T sum;  // 区间和
  T addtag;  // 加法懒标记

  // 左右子节点
  Node *left, *right;

  Node(int l_, int r_, T sum_) : l(l_), r(r_), sum(sum_), addtag(0), left(nullptr), right(nullptr) {}
};

template<typename T>
struct SegmentTree {
  void destroy(Node<T>* node);
  // 析构函数
  ~SegmentTree() { destroy(root); }

  // 建树
  Node<T>* build(int l_, int r_);
  Node<T>* build(int l_, int r_, std::vector<T>& a);
  SegmentTree(int n_) : n(n_) { root = build(1, n); }
  SegmentTree(int n_, std::vector<T>& a) : n(n_) { root = build(1, n, a); }

  // 查询区间和
  T querySeqSum(Node<T>* node, int l_, int r_);
  T querySeqSum(int l_, int r_);

  // 单点加
  void pointAdd(Node<T>* node, int pos, T val);
  void pointAdd(int pos, T val);

  // 区间加
  void seqAdd(Node<T>* node, int l_, int r_, T val);
  void seqAdd(int l_, int r_, T val);

  Node<T>* root;
  int n;  // 线段树范围
};

template<typename T>
Node<T>* SegmentTree<T>::build(int l_, int r_) {
  if (l_ > r_) {
    return nullptr;
  }
  auto node = new Node<T>(l_, r_, 0);
  if (l_ == r_) {
    return node;
  }
  int mid = (l_ + r_) / 2;
  node->left = build(l_, mid);
  node->right = build(mid + 1, r_);
  return node;
}

template<typename T>
Node<T>* SegmentTree<T>::build(int l_, int r_, std::vector<T>& a) {
  if (l_ > r_) {
    return nullptr;
  }
  auto node = new Node<T>(l_, r_, 0);
  if (l_ == r_) {
    node->sum = a[l_];
    return node;
  }
  int mid = (l_ + r_) / 2;
  node->left = build(l_, mid, a);
  node->right = build(mid + 1, r_, a);

  // pushup 操作
  if (node->left && node->right) {
    node->sum = node->left->sum + node->right->sum;
  }

  return node;
}

template<typename T>
void SegmentTree<T>::destroy(Node<T> *node) {
  if (node == nullptr) {
    return;
  }
  destroy(node->left);
  destroy(node->right);
  delete node;
}

template<typename T>
T SegmentTree<T>::querySeqSum(Node<T> *node, int l_, int r_) {
  if (node == nullptr || l_ > node->r || r_ < node->l) {
    return T();
  }

  // pushdown 操作
  if (node->addtag && node->left && node->right) {
    node->left->addtag += node->addtag;
    node->right->addtag += node->addtag;

    node->left->sum += (node->left->r - node->left->l + 1) * node->addtag;
    node->right->sum += (node->right->r - node->right->l + 1) * node->addtag;

    node->addtag = 0;
  }

  if (l_ <= node->l && node->r <= r_) {
    return node->sum;
  }
  return querySeqSum(node->left, l_, r_) + querySeqSum(node->right, l_, r_);
}

template<typename T>
T SegmentTree<T>::querySeqSum(int l_, int r_) {
  return querySeqSum(root, l_, r_);
}

template<typename T>
void SegmentTree<T>::pointAdd(Node<T> *node, int pos, T val) {
  if (node == nullptr || pos < node->l || pos > node->r) {
    return;
  }
  if (node->l == node->r) {
    node->sum += val;
    return;
  }
  pointAdd(node->left, pos, val);
  pointAdd(node->right, pos, val);

  // pushup 操作
  if (node->left && node->right) {
    node->sum = node->left->sum + node->right->sum;
  }
}

template<typename T>
void SegmentTree<T>::pointAdd(int pos, T val) {
  pointAdd(root, pos, val);
}

template<typename T>
void SegmentTree<T>::seqAdd(Node<T>* node, int l_, int r_, T val) {
  if (node == nullptr || r_ < node->l || l_ > node->r) {
    return;
  }
  if (node->l >= l_ && node->r <= r_) {
    node->sum += val * (node->r - node->l + 1);
    node->addtag += val;
    return;
  }

  // pushdown 操作
  if (node->addtag && node->left && node->right) {
    node->left->addtag += node->addtag;
    node->right->addtag += node->addtag;

    node->left->sum += (node->left->r - node->left->l + 1) * node->addtag;
    node->right->sum += (node->right->r - node->right->l + 1) * node->addtag;

    node->addtag = 0;
  }

  seqAdd(node->left, l_, r_, val);
  seqAdd(node->right, l_, r_, val);

  // pushup 操作
  if (node->left && node->right) {
    node->sum = node->left->sum + node->right->sum;
  }
}

template<typename T>
void SegmentTree<T>::seqAdd(int l_, int r_, T val) {
  seqAdd(root, l_, r_, val);
}
posted @   hacker_dvd  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示