#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; }
SegmentTree 的基本操作
猜你喜欢
转载自blog.csdn.net/a673786103/article/details/80216923
今日推荐
周排行