Segment Tree
死線斷裂術
建北電資小社課 演算法
Segment Tree
線段樹
- 225班
- 電子計算機研習社_學術長
- 綽號807
這我

這建北電資
線段樹
線段樹
線段樹
怎麼分區間?
從中間切一半
1
5
5
8
4
3
7
2
6
13
7
9
19
16
35
若 n 為2的冪次
n 代表資料長度
如果資料長度不是2的冪次
1
5
8
4
3
7
2
1
13
7
9
14
16
30
這樣也行
若 n 非2的冪次
n 代表資料長度
- 建樹 : O(nlog(n)) 或 O(n)
- 查詢 : O(log(n))
- 修改 : O(log(n))
複雜度
複雜度比較
線段樹 | 前綴和 | 差分 | |
---|---|---|---|
建表 |
|
||
區間查詢 | |||
單點修改 | |||
區間修改 |
O(n)
O(n)
O(log(n))
O(1)
O(n)
O(log(n))
O(n)
O(1)
O(log(n))
O(n)
O(1)
存樹
- 用 struct 存
- 左子節點指標
- 右子節點指標
- 值
指標型存法
struct node{ int value; node *left, *right; };
- 開 4 倍大的陣列
- 以節點 x
- 左子節點位置 x×2
- 右子節點位置 x×2+1
陣列型存法 (偽指標型)
int n; vector<int> data(n*4,0);
註: n 代表原資料長度
4 倍 哪來的
若 n 為2的冪次
註: n 代表原資料長度
- 最下層有 n 個 (節點)
- 上層有 n÷2 個
- 上上層有 n÷2÷2 個
- 上上上層有 n÷2÷2÷2 個
. . .
若 n 為2的冪次
註: n 代表原資料長度
- 有 log2n+1 層
- 需要 2−12log2n+1−1≈2n 個 (節點)
若 n 不是 2的冪次
註: n 代表原資料長度
- n 到 2n 間有一個 n 的冪次
- 他需要的空間小於 2n×2=4n
- 我不會證明,你可以接受就好
- 開 2 倍大的陣列
- 以節點 x
- 左子節點位置 x×2
- 右子節點位置 x×2+1
迭代式線段樹陣列型存法
int n; vector<int> data(n*2,0);
註: n 代表原資料長度
2 倍 哪來的
有點複雜等等再說
建樹
Create
- 遞迴將左右子節點計算完
- 結和左右子節點值 (pull)
- 遞迴完就結束了
建樹 遞迴陣列型
線段樹 建樹 code
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
# PRESENTING CODE
初始化 nodes 大小
宣告 變數
到葉節點 複製值進去
取得中間值 區分左右子節點的區間
左區間在 x×2
右區間在 x×2+1
遞迴計算子節點值
結合左右子節點值 (pull)
遞迴函式
還沒到葉節點
變數解釋
n 資料長度
nodes 節點值
data 原始資料
l r 左右邊界
mid 中介: 區分左右子區間
it 偽指標: 指向結點在nodes的位置
註: 皆為左閉右開 0-base
- 少於4n 個節點
- 每個節點只跑一次
- 複雜度: O(n)
複雜度分析
查詢
Read
- 遞迴下去做
- 三種可能
- 完全在左
- 完全在右
- 左右都有
查詢
線段樹 查詢 code
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } };
# PRESENTING CODE
已經找到了
取得中間值 區分左右節點範圍
完全在左
完全在右
左右都有
左右都有
注意範圍
變數解釋
nodes 節點值
queryL queryR 搜尋左右界
l r 左右邊界
mid 中介: 區分左右子區間
it 偽指標: 指向結點在nodes的位置
註: 皆為左閉右開 0-base
- 他是好的
- 一層最多碰到4的節點
- 深度 : log(n)
- 複雜度 : O(log(n))
複雜度
單點修改
Update
線段樹 單點修改 code
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify1(int pos, int modifyValue, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = modifyValue; return; } int mid = (l + r) / 2; if (pos < mid) modify1(pos, modifyValue, l, mid, it * 2); else modify1(pos, modifyValue, mid, r, it * 2 + 1); // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify1(int pos, int modifyValue, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = modifyValue; return; } int mid = (l + r) / 2; if (pos < mid) modify1(pos, modifyValue, l, mid, it * 2); else modify1(pos, modifyValue, mid, r, it * 2 + 1); // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify1(int pos, int modifyValue, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = modifyValue; return; } int mid = (l + r) / 2; if (pos < mid) modify1(pos, modifyValue, l, mid, it * 2); else modify1(pos, modifyValue, mid, r, it * 2 + 1); // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify1(int pos, int modifyValue, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = modifyValue; return; } int mid = (l + r) / 2; if (pos < mid) modify1(pos, modifyValue, l, mid, it * 2); else modify1(pos, modifyValue, mid, r, it * 2 + 1); // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify1(int pos, int modifyValue, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = modifyValue; return; } int mid = (l + r) / 2; if (pos < mid) modify1(pos, modifyValue, l, mid, it * 2); else modify1(pos, modifyValue, mid, r, it * 2 + 1); // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify1(int pos, int modifyValue, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = modifyValue; return; } int mid = (l + r) / 2; if (pos < mid) modify1(pos, modifyValue, l, mid, it * 2); else modify1(pos, modifyValue, mid, r, it * 2 + 1); // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify1(int pos, int modifyValue, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = modifyValue; return; } int mid = (l + r) / 2; if (pos < mid) modify1(pos, modifyValue, l, mid, it * 2); else modify1(pos, modifyValue, mid, r, it * 2 + 1); // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
# PRESENTING CODE
已經找到了 直接修改
取得中間值 區分左右節點範圍
在左
在右
修改目前節點值 (pull)
註: 皆為左閉右開 0-base
變數解釋
nodes 節點值
queryL queryR 搜尋左右界
l r 左右邊界
mid 中介: 區分左右子區間
it 偽指標: 指向結點在nodes的位置
- 改值後 pull 上來
- 複雜度就是最深深度
- 複雜度 O(log(n))
複雜度
多點修改
Update
- 懶人標記 (tag)
- 兩種做法
- 懶標下推 (推薦)
- 懶標永久化
懶標
線段樹 懶標下推 code
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
# PRESENTING CODE
新增宣告 tags (懶標)
build 函式 不需要改
註: 皆為左閉右開 0-base
變數解釋
nodes 節點值
tags 懶標值
l r 左右邊界
mid 中介: 區分左右子區間
it 偽指標: 指向結點在nodes的位置
線段樹 懶標下推 code push()
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
# PRESENTING CODE
需要知道 子節點範圍
左右子節點都加上
懶標×範圍大小
更新子節點懶標
懶標歸0
push 完成
註: 皆為左閉右開 0-base
變數解釋
nodes 節點值
tags 懶標值
l r 左右邊界
mid 中介: 區分左右子區間
it 偽指標: 指向結點在nodes的位置
線段樹 懶標下推 code query()
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
# PRESENTING CODE
每次到了就下推
註: 皆為左閉右開 0-base
變數解釋
nodes 節點值
queryL queryR 搜尋左右界
l r 左右邊界
mid 中介: 區分左右子區間
it 偽指標: 指向結點在nodes的位置
線段樹 懶標下推 code modify()
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n * 4); tags.resize(n * 4); build(data, 0, n); } void build(const vector<int> &data, int l, int r, int it = 1) { if (r - l == 1) { nodes[it] = data[l]; return; } int mid = (l + r) / 2; build(data, l, mid, it * 2); build(data, mid, r, it * 2 + 1); nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } void push(int l, int r, int it) { int mid = (l + r) / 2; nodes[it * 2] += tags[it] * (mid - l); nodes[it * 2 + 1] += tags[it] * (r - mid); tags[it * 2] += tags[it]; tags[it * 2 + 1] += tags[it]; tags[it] = 0; return; } int query(int queryL, int queryR, int l, int r, int it = 1) { if (queryL == l && queryR == r) return nodes[it]; push(l, r, it); int mid = (l + r) / 2; if (queryR <= mid) return query(queryL, queryR, l, mid, it * 2); else if (queryL >= mid) return query(queryL, queryR, mid, r, it * 2 + 1); else return query(queryL, mid, l, mid, it * 2) + query(mid, queryR, mid, r, it * 2 + 1); } void modify(int modifyL, int modifyR, int delta, int l, int r, int it = 1) { if (modifyL == l && modifyR == r) { nodes[it] += delta * (r - l); tags[it] += delta; return; } push(l, r, it); int mid = (l + r) / 2; if (modifyR <= mid) modify(modifyL, modifyR, delta, l, mid, it * 2); else if (modifyL >= mid) modify(modifyL, modifyR, delta, mid, r, it * 2 + 1); else { modify(modifyL, mid, delta, l, mid, it * 2); modify(mid, modifyR, delta, mid, r, it * 2 + 1); } // pull nodes[it] = nodes[it * 2] + nodes[it * 2 + 1]; return; } };
# PRESENTING CODE
如果範圍正確
更新此節點值
加上懶標
有點像單點修改+區間查詢
下推
完全在左
完全在右
取得中間值
左右都有
修改目前節點值 (pull)
註: 皆為左閉右開 0-base
變數解釋
nodes 節點值
tags 懶標值
modifyL modifyR 修改左右區間
delta 修改增加值
複雜度
補充
迭代式線段樹
- 節省一半記憶體
- 常數小
- O(n) 建樹 ↔ 遞迴式線段樹
- 有點懸的存圖
- code 短
優點
存圖方式 n 為2的冪次
註: n 代表原資料長度

迭代式線段樹 存圖 code
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
# PRESENTING CODE
迭代式線段樹 build code
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
# PRESENTING CODE
迭代式線段樹 query code
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
# PRESENTING CODE
迭代式線段樹 單點修改 code
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; SegmentTree() : n(0) { nodes.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { for (pos += n; pos >>= 1;) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1]; return; } int query(int l, int r) { int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify1(int pos, int modifyValue) { nodes[pos + n] = modifyValue; pull(pos); return; } };
# PRESENTING CODE
- 一樣要懶標
多點修改
迭代式線段樹 code 懶標
#include <bits/stdc++.h> #define int long long using namespace std; struct SegmentTree { int n; vector<int> nodes; vector<int> tags; SegmentTree() : n(0) { nodes.clear(); tags.clear(); } SegmentTree(vector<int> &data) : n(data.size()) { nodes.resize(n << 1, 0); tags.resize(n, 0); build(data); } void build(const vector<int> &data) { for (int i = n; i--;) nodes[i + n] = data[i]; for (int i = n; i--;) nodes[i] = nodes[i << 1] + nodes[i << 1 | 1]; return; } void pull(int pos) { pos += n; for (int h = 1; pos >>= 1; h++) nodes[pos] = nodes[pos << 1] + nodes[pos << 1 | 1] + (tags[pos] << h); return; } void push(int pos) { pos += n; for (int h = __lg(pos), it = 1; h--; it = pos >> h) { if (!tags[it]) continue; nodes[it << 1] += tags[it] << h; nodes[it << 1 | 1] += tags[it] << h; if (h) { tags[it << 1] += tags[it]; tags[it << 1 | 1] += tags[it]; } tags[it] = 0; } } int query(int l, int r) { push(l), push(r - 1); int sum = 0; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) sum += nodes[l++]; if (r & 1) sum += nodes[--r]; } return sum; } void modify(int l, int r, int delta) { push(l), push(r - 1); int l2 = l + n, r2 = r + n; if (l2 & 1) nodes[l2++] += delta; if (r2 & 1) nodes[--r2] += delta; for (int h = 1; (l2 >>= 1) < (r2 >>= 1); h++) { if (l2 & 1) tags[l2] += delta, nodes[l2++] += delta << h; if (r2 & 1) tags[--r2] += delta, nodes[r2] += delta << h; } pull(l), pull(r - 1); } }; signed main() { int n, q; cin >> n >> q; vector<int> data(n); for (int &i : data) cin >> i; SegmentTree st(data); for (int mode, l, r, delta; q--;) { cin >> mode; if (mode == 1) { cin >> l >> r >> delta; st.modify(l - 1, r, delta); } else { cin >> l; cout << st.query(l - 1, l) << "\n"; } } }
# PRESENTING CODE
指標型線段樹
指標型線段樹
#include <bits/stdc++.h> #define int long long using namespace std; struct node { int l, r; int value = 0, tag = 0; node *pointerL = nullptr, *pointerR = nullptr; node(int _l, int _r) : l(_l), r(_r) {} node(vector<int> &data) { l = 0; r = data.size(); build(data); } void build(const vector<int> &data) { if (r - l == 1) { value = data[l]; return; } int mid = l + r >> 1; pointerL = new node(l, mid); pointerR = new node(mid, r); pointerL->build(data); pointerR->build(data); value = pointerL->value + pointerR->value; return; } void push() { if (r - l == 1) return; pointerL->value += tag * (pointerL->r - l); pointerR->value += tag * (r - pointerR->l); pointerL->tag += tag; pointerR->tag += tag; tag = 0; } int query(int queryL, int queryR) { if (queryL == l && queryR == r) return value; push(); if (queryR <= pointerL->r) return pointerL->query(queryL, queryR); else if (queryL >= pointerR->l) return pointerR->query(queryL, queryR); else return pointerL->query(queryL, pointerL->r) + pointerR->query(pointerR->l, queryR); } void modify(int modifyL, int modifyR, int delta) { if (modifyL == l && modifyR == r) { value += delta * (r - l); tag += delta; return; } push(); if (modifyR <= pointerL->r) pointerL->modify(modifyL, modifyR, delta); else if (modifyL >= pointerR->l) pointerR->modify(modifyL, modifyR, delta); else { pointerL->modify(modifyL, pointerL->r, delta); pointerR->modify(pointerR->l, modifyR, delta); } // pull value = pointerL->value + pointerR->value; return; } }; signed main() { int n, q; cin >> n >> q; vector<int> data(n); for (int &i : data) cin >> i; node st(data); for (int mode, l, r, u, k; q--;) { cin >> mode; if (mode == 1) { cin >> l >> r >> u; st.modify(l - 1, r, u); } else { cin >> k; cout << st.query(k - 1, k) << "\n"; } } }
# PRESENTING CODE
平衡二元樹
- 二元
- 樹
二元樹
🌲
樹 結構
根節點
葉節點
分支
根節點的
子節點
- 節點 + 分支
- 根節點 : 節點根源
- 葉節點 : 無子節點
- 子節點 : 向下連結到的
- 深度 : 根到此節點的路徑長
樹結構
樹 結構
根節點
葉節點
分支
根節點的
子節點
- 每個節點至多 2 個子節點
二元樹
二元?
至多兩個子節點
二元樹 結構
根節點
葉節點
根節點的
子節點
分支
SegmentTree
By 建中店自計算機研習社學術長807⁸⁰⁷
SegmentTree
- 332