SegmentTree 的基本操作


#pragma once
#include <iostream>

#define inf 0x3f3f3f3f
template<typename T>
class SegmentTree {

private:
	T* data;
	T* tree;
	T* add;
	int number;

	int getLeftIndex(int treeIndex) {
		return treeIndex * 2 + 1;
	}
	int getRightIndex(int treeIndex) {
		return treeIndex * 2 + 2;
	}
	//以treeIndex为根节点,【l,r】创建线段树
	void bulidSegmentTree(int treeIndex, int l, int r) {
		if (l == r) {
			tree[treeIndex] = data[l];
			return;
		}
		// 不使用(l+r)/2因为可能会超出整数范围
		int mid = l + (r - l) / 2;
		int leftIndex = getLeftIndex(treeIndex);
		int RightIndex = getRightIndex(treeIndex);
		//分治
		bulidSegmentTree(leftIndex, l, mid);
		bulidSegmentTree(RightIndex, mid + 1, r);

	//	tree[treeIndex] = data[l] + data[r];
		//融合
		tree[treeIndex] = merge(tree[leftIndex],tree[RightIndex]);
	}
	int query1(int rootNode, int l, int r, int queryL, int queryR) {
		
		if (l == queryL && queryR == r)
			return tree[rootNode];
		int mid = l + (r - l) / 2;
		if (queryR <= mid)
			return query1(rootNode * 2 + 1, l, mid, queryL, queryR);
		else if (queryL >= mid + 1)
			return query1(rootNode * 2 + 2, mid + 1, r, queryL, queryR);
		else
			return merge(query1(rootNode * 2 + 1, l, mid, queryL, mid), 
				query1(rootNode * 2 + 2, mid + 1, r, mid+1, queryR));
		
	}
	//在【l,r】范围内, 将p的值修改为v
	void updataPoint(int rootNode, int l, int r, int p, int v) {
		if (l == r) {
			tree[rootNode] = v;
			return;
		}
		int mid = l + (r - l) / 2;
		if (p <= mid)
			updataPoint(rootNode * 2 + 1, l, mid, p, v);
		else if( p >= mid+1)
			updataPoint(rootNode * 2 + 2, mid + 1, r, p, v);
		tree[rootNode] = merge(tree[rootNode*2+1],tree[rootNode*2+2]);
	}

    void updata(int rootNode, int l, int r, int ql, int qr, int v) {
		if (ql <= l && qr >= r) {
			add[rootNode] += v;
			tree[rootNode] += v * (r - l + 1);
			return;
		}

		pushDwon(rootNode,l,r);
		int mid = l + (r - l) / 2;
		int left = rootNode * 2 + 1;
		int right = rootNode * 2 + 2;

		if (ql <= mid)
			updata(left, l, mid, ql, qr, v);
		if (qr >= mid + 1)
			updata(right, mid + 1, r, ql, qr, v);
		tree[rootNode] = merge(tree[left],tree[right]);
	}

    void pushDwon(int rootNode,int l, int r){
		
		if (add[rootNode]) {
			int left = rootNode * 2 + 1;
			int right = rootNode * 2 + 2;
			add[left] += add[rootNode];
			add[right] += add[rootNode];

			
			int mid = l + (r - l) / 2;

	//		tree[left] += v * (mid-l+1);		//[l,mid]
	//		tree[right] += v * (r - mid);		//[mid+1,r]
			tree[left] = add[rootNode] * (mid - l + 1);
			tree[right] = add[rootNode] * (r - mid);
			add[rootNode] = 0;
		}
	}


 public:
     SegmentTree(){ }
     SegmentTree(T arr[],int n){
 	
	this->number = n;
	data = new T[n];
	add = new T[n * 4]{ 0 };
	for (int i = 0; i < n; i++) {
		data[i] = arr[i];
	}
	tree = new T[n * 4];
	for (int i = 0; i < n * 4; i++) {
		tree[i] = inf;
	}
	bulidSegmentTree(0,0,n-1);
}
	T merge(T a, T b) {return a + b;}
	int getTreelength() {return 4 * number;}
	void println() {
		cout << "[ ";
		for (int i = 0; i < getTreelength(); i++) {
			if (tree[i] != inf)
				cout << tree[i];
			else
				cout << "NUll";
			if (i < getTreelength() - 1)
				cout << ",";
		}
		cout << " ]" << endl;
	}
	//区间查询
	int query1(int queryL, int queryR) {
		return query1(0, 0, number - 1, queryL, queryR);
	}

    //点更新 P位置的值更新为v
	void updataPoint(int p, int v) {
		updataPoint(0, 0, number-1, p, v);
	}

    //区间更新
	void updata(int l, int r, int v) {
		updata(0, 0, number - 1, l, r, v);
	}
};



#include <iostream>
#include "SegmentTree.h"
using namespace std;

int main()
{
    int arr[] = { 1,2,3,4,5,6 };
    SegmentTree<int> segment(arr, 6);
    segment.println();
    cout << segment.query1(0, 5) << endl;
    //segment.updataPoint(1,3);
    //cout << segment.query1(0, 5) << endl;
    cout << segment.query1(0, 2) << endl;
    segment.updata(0, 2, 2);
    cout << segment.query1(0, 2) << endl;
    system("pause");
    
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值