[模版]线段树

#include <bits/stdc++.h>
using namespace std;

// _TYPE = {int, long long, double, float}
template <class _TYPE>
class Segment_Tree {
private:
	struct TreeNode;
public:
	int _SIZE;

	TreeNode* root;

	Segment_Tree() {}
	Segment_Tree(int _SIZE, vector<_TYPE> &_NUMS): _SIZE(_SIZE) {root = BuildTree(0, _SIZE - 1, _NUMS);}
	_TYPE sum(int _LEFT, int _RIGHT) {return Query(root, _LEFT, _RIGHT);}
	void add(int _LEFT, int _RIGHT, _TYPE _NUMS) {Modify(root, _LEFT, _RIGHT, _NUMS);}
private:
	struct TreeNode {
		int _LEFT, _RIGHT, size;
		_TYPE val, tmp;
		TreeNode *left, *right;
		TreeNode() {}
		TreeNode(int __LEFT, int __RIGHT, int _val): _LEFT(__LEFT), _RIGHT(__RIGHT), val(_val), left(nullptr), right(nullptr), tmp(0) {
			size = __RIGHT - __LEFT + 1;
		}
		TreeNode(int __LEFT, int __RIGHT, int _val, TreeNode *_left, TreeNode *_right): _LEFT(__LEFT), _RIGHT(__RIGHT), val(_val), left(_left), right(_right), tmp(0) {
			size = __RIGHT - __LEFT + 1;
		}
	};

	TreeNode *BuildTree(int _LEFT, int _RIGHT, vector<_TYPE> &_NUMS) {
		int _MID = (_LEFT + _RIGHT) / 2;

		if (_LEFT == _RIGHT)
			return new TreeNode(_LEFT, _RIGHT, _NUMS[_MID]);

		TreeNode *_left = BuildTree(_LEFT, _MID, _NUMS), *_right = BuildTree(_MID + 1, _RIGHT, _NUMS);
		return new TreeNode(_LEFT, _RIGHT, _left->val + _right->val, _left, _right);
	}

	void push_down(TreeNode *node) {
		node->val += node->tmp * node->size;

		if (node->left != nullptr && node->right != nullptr) {
			node->left->tmp += node->tmp;
			node->right->tmp += node->tmp;
		}

		node->tmp = 0;
	}

	_TYPE Query(TreeNode *node, int _LEFT, int _RIGHT) {
		if (_LEFT > _RIGHT)
			return _TYPE(0);

		push_down(node);
		int _MID = (node->_LEFT + node->_RIGHT) / 2;

		if (node->_LEFT == _LEFT && node->_RIGHT == _RIGHT)
			return node->val;

		if (_MID < _LEFT)
			return Query(node->right, _LEFT, _RIGHT);
		else if (_RIGHT <= _MID)
			return Query(node->left, _LEFT, _RIGHT);
		else
			return Query(node->left, _LEFT, _MID) + Query(node->right, _MID + 1, _RIGHT);
	}

	void Modify(TreeNode *node, int _LEFT, int _RIGHT, _TYPE _NUMS) {
		if (node->_LEFT == _LEFT && node->_RIGHT == _RIGHT) {
			node->tmp += _NUMS;
			push_down(node);
			return;
		}

		push_down(node);
		int _MID = (node->_LEFT + node->_RIGHT) / 2;

		if (_MID < _LEFT)
			Modify(node->right, _LEFT, _RIGHT, _NUMS);
		else if (_RIGHT <= _MID)
			Modify(node->left, _LEFT, _RIGHT, _NUMS);
		else
			Modify(node->left, _LEFT, _MID, _NUMS), Modify(node->right, _MID + 1, _RIGHT, _NUMS);

		push_down(node->left), push_down(node->right);
		node->val = node->left->val + node->right->val;
	}
};
以下是acwing模板线段树的示例代码: ```cpp const int N = 100010; int n, m; int a[N]; struct Node { int l, r; int v, lazy; } tree[N * 4]; void pushup(int x) { tree[x].v = tree[x * 2].v + tree[x * 2 + 1].v; } void pushdown(int x) { if (tree[x].lazy) { int l = tree[x].l, r = tree[x].r; int mid = (l + r) >> 1; tree[x * 2].v += tree[x].lazy * (mid - l + 1); tree[x * 2 + 1].v += tree[x].lazy * (r - mid); tree[x * 2].lazy += tree[x].lazy; tree[x * 2 + 1].lazy += tree[x].lazy; tree[x].lazy = 0; } } void build(int x, int l, int r) { tree[x].l = l, tree[x].r = r; if (l == r) { tree[x].v = a[l]; return; } int mid = (l + r) >> 1; build(x * 2 l, mid); build(x * 2 + 1, mid +1, r); pushup(x); } void modify(int x, int l, int r, int val) { if (tree[x].l >= l && tree[x].r <= r) { tree[x].v += val * (tree[x].r - tree[x].l + 1); tree[x].lazy += val; return; } pushdown(x); int mid = (tree[x].l + tree[x].r) >> 1; if (l <= mid) modify(x * 2, l, r, val); if (r > mid) modify(x * 2 + 1, l, r, val); pushup(x); } int query(int x, int l, int r) { if (tree[x].l >= l && tree[x].r <= r) { return tree[x].v; } pushdown(x); int mid = (tree[x].l + tree[x].r) >> 1; int sum = 0; if (l <= mid) sum += query(x * 2, l, r); if (r > mid) sum += query(x * 2 + 1, l, r); return sum; } int main() { cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> a[i]; } build(1, 1, n); while (m--) { int op, l, r, val; cin >> op; if (op == 1) { cin >> l >> r >> val; modify(1, l, r, val); } else if (op == 2) { cin >> l >> r; cout << query(1, l, r) << endl; } } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值