1 #include <bits/stdc++.h>
2 #include <unordered_map>
3 using namespace std;
4 //线段树成,node版本;
5 class Node{
6 public:
7 Node * left;
8 Node * right;
9 int val;
10 //懒惰标记
11 int add;
12 Node():left(nullptr),right(nullptr),val(0),add(0){};
13 };
14 class SegmentTree{
15 private:
16 Node * node;
17 int N = 1e9;
18 public:
19 //如果给了arr的具体范围,start,end;建树;
20 void buildtree(Node * node,int start,int end,vector<int> arr){
21 //抵达叶子结点
22 if(start == end){
23 node->val = arr[start];
24 return;
25 }
26 int mid = start+(end-start)/2;
27 buildtree(node->left,start,mid,arr);
28 buildtree(node->right,mid+1,end,arr);
29 //后序位置
30 node->val = node->left->val + node->right->val;
31 }
32 //如果没有给arr,不知道具体范围,只有数据的取值范围,且很大,使用动态开点的方法;
33 //什么是动态开点,就是一开始不建树,而是在【查询】和【更新】的时候,进行结点的建立。
34
35 //【更新】,我们如果要更新【2-4】,则只更新【2-2】和【3-4】;对于【3-3】【4-4】是通过懒惰标记下推来更新的;
36 //更新,node是头结点,stanr,end是总的区间范围,left,right是需要修改的区间范围,val是该区间需要加上的值(+1,/或减-1)
37 void update(Node * node,int start,int end,int left,int right,int val){
38 //找到了要更新的区间
39 if(left <= start && end <= right){
40 //node的值更新来自下面所有子树的更新之和;
41 node->val += ((end-start)+1)*val;
42 //增加懒惰标记
43 node->add = val;
44 return;
45 }
46 //没找到满足的区间,继续向下找
47 int mid = start+(end-start)/2;
48 //下推标记
49 pushDown(node,mid-start+1,end-mid);
50 //递归
51 if(left <= mid) update(node->left,start,mid,left,right,val);
52 if(mid < right) update(node->right,mid+1,end,left,right,val);
53 //后序位置
54 node->val = node->left->val + node->right->val;
55 }
56
57 //懒惰标记下推,node是传入的结点,leftNum是左叶子结点数的个数,rightNum是右叶子结点数的个数
58 void pushDown(Node * node,int leftNum,int rightNum) {
59 //动态开点
60 if (node->left == nullptr) node->left = new Node();
61 if (node->right == nullptr) node->right = new Node();
62 //如果node没有懒惰标记,不用下推了
63 if (node->add == 0) return;
64 //否则,更新值
65 node->left->val += node->add * leftNum;
66 node->right->val += node->add * rightNum;
67 //add下推
68 node->left->add = node->add;
69 node->right->add = node->add;
70 //取消当前结点的标记
71 node->add = 0;
72 }
73
74 //查询,在satrt,end范围里查询left,right区间的结果,node表示的范围是【start,end】的值;
75 int query(Node * node,int start,int end,int left,int right){
76 //找到了要查询的区间
77 if(left <= start && end <= right){
78 return node->val;
79 }
80 //往下找
81 int mid = start + (end-start)/2;
82 int ans = 0;
83 //标记下推
84 pushDown(node,mid-start+1,end-mid);
85 if(left <= mid) ans += query(node->left,start,mid,left,right);
86 if(mid < right) ans += query(node->right,mid+1,end,left,right);
87 return ans;
88 }
89 };
90 int main(){
91
92 }