Skip to content

Commit 77a8a2a

Browse files
Add files via upload
1 parent 71601a7 commit 77a8a2a

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// 如果使用常规操作,查询和更新两个操作一个是on的复杂度,另外一个是o1的复杂度,但是如果使用
2+
// 区间树,就可以将两个操作都变成logn的复杂度
3+
4+
// Runtime: 32 ms, faster than 91.34% of C++ online submissions for Range Sum Query - Mutable.
5+
// Memory Usage: 19.7 MB, less than 8.33% of C++ online submissions for Range Sum Query - Mutable.
6+
7+
struct cell
8+
{
9+
cell() : start(-1), end(-1), sum(0) {}
10+
int start, end;
11+
int sum;
12+
};
13+
14+
class NumArray
15+
{
16+
public:
17+
18+
// 构建区间树
19+
NumArray(vector<int>& nums)
20+
{
21+
// 边界条件处理
22+
if (nums.size() == 0) return;
23+
24+
// 计算数组的大小
25+
int rightPtr = nums.size() - 1, layer = 1;
26+
while (rightPtr)
27+
rightPtr /= 2, ++layer;
28+
29+
// 在定义默认构造函数后,这样做之后每个新添加上的元素会按照默认构造进行初始化
30+
tree.resize(pow(2, layer) - 1);
31+
32+
// 建立线段树
33+
buildSegmentTree(0, nums.size() - 1, 0, nums);
34+
}
35+
36+
// 更新区间树中的元素 logn的时间复杂度
37+
void update(int i, int val)
38+
{
39+
if (tree.size() != 0)
40+
{
41+
int start = 0, end = tree.front().end;
42+
int index = 0;
43+
44+
// dfs查找
45+
while (start != end)
46+
{
47+
int mid = (start + end) / 2;
48+
if (mid >= i)
49+
end = mid, index = index * 2 + 1;
50+
else
51+
start = mid + 1, index = index * 2 + 2;
52+
}
53+
54+
int offset = val - tree[index].sum;
55+
56+
// 回溯整个路径
57+
while (true)
58+
{
59+
tree[index].sum += offset;
60+
if (index == 0) break;
61+
62+
if (index & 1) index = index / 2; // 奇数节点
63+
else index = index / 2 - 1; // 偶数节点
64+
}
65+
}
66+
}
67+
68+
// 查询函数 同样是logn的时间复杂度
69+
int sumRange(int start, int end)
70+
{
71+
return (tree.size() != 0 && start <= end && start >= 0) ? query(start, end, 0) : 0;
72+
}
73+
74+
private:
75+
vector<cell> tree;
76+
private:
77+
int query(int start, int end, int index)
78+
{
79+
int mid = (tree[index].start + tree[index].end) / 2;
80+
81+
if (start == tree[index].start && end == tree[index].end)
82+
return tree[index].sum;
83+
else if (end <= mid)
84+
return query(start, end, 2 * index + 1);
85+
else if (start > mid)
86+
return query(start, end, 2 * index + 2);
87+
else
88+
return query(start, mid, 2 * index + 1) + query(mid + 1, end, 2 * index + 2);
89+
}
90+
91+
int buildSegmentTree(int start, int end, int index, const vector<int>& nums)
92+
{
93+
if (start == end)
94+
{
95+
tree[index].start = start;
96+
tree[index].end = start;
97+
tree[index].sum = nums[start];
98+
}
99+
else
100+
{
101+
int mid = (start + end) / 2;
102+
int leftSum = buildSegmentTree(start, mid, 2 * index + 1, nums);
103+
int rightSum = buildSegmentTree(mid + 1, end, 2 * index + 2, nums);
104+
105+
tree[index].start = start;
106+
tree[index].end = end;
107+
tree[index].sum = leftSum + rightSum;
108+
}
109+
return tree[index].sum;
110+
}
111+
};

0 commit comments

Comments
 (0)