题目链接:单点修改,区间查询
build:基于后序遍历和区间二分的思想,递归建树
change:
- r < x or l > x&#xff0c;当前区间与要修改的点无交集&#xff0c;直接return掉
- l &#61;&#61; r and l &#61;&#61; x&#xff0c;这个点为要修改的点&#xff0c;把对应位置修改后return
- 其他情况&#xff0c;递归找要修改的点&#xff0c;同时维护修改后的树
query&#xff1a;
- r < s or l > t&#xff0c;当前区间与查询区间无交集&#xff0c;返回0
- s <&#61; l and r <&#61; t&#xff0c;当前区间为查询区间的子区间&#xff0c;返回该区间权值
- 当前区间与查询区间有部分交集&#xff0c;递归查询子区间的权值
#include
using namespace std;
typedef long long ll;
ll d[4000020], a[1000005];
void build(ll p, ll l, ll r) {if (l &#61;&#61; r) {d[p] &#61; a[l];return;}ll m &#61; l &#43; r >> 1;build(p <<1, l, m);build(p <<1 | 1, m &#43; 1, r);d[p] &#61; d[p <<1] &#43; d[p <<1 | 1];
}
void change(ll p, ll l, ll r, ll x, ll v) {if (r x) {return;} else if (l &#61;&#61; r && l &#61;&#61; x) {d[p] &#43;&#61; v;return;} else {ll m &#61; l &#43; r >> 1;change(p <<1, l, m, x, v);change(p <<1 | 1, m &#43; 1, r, x, v);d[p] &#61; d[p <<1] &#43; d[p <<1 | 1];}
}
ll query(ll p, ll l, ll r, ll s, ll t) {if (r t) {return 0;} else if (s <&#61; l && r <&#61; t) {return d[p];} else {ll m &#61; l &#43; r >> 1;return query(p <<1, l, m, s, t) &#43; query(p <<1 | 1, m &#43; 1, r, s, t);}
}
int main() {ll n, m;cin >> n >> m;for (ll i &#61; 0; i > a[i];}build(1, 0, n - 1);while (m--) {ll op, l, r;cin >> op >> l >> r;if (op &#61;&#61; 1) {change(1, 1, n, l, r);} else {cout <}
二维线段树&#xff1a;
leetcode308.二维区域和检索-可变
给你一个二维矩阵 matrix &#xff0c;你需要处理下面两种类型的若干次查询&#xff1a;
更新&#xff1a;更新 matrix 中某个单元的值。
求和&#xff1a;计算矩阵 matrix 中某一矩形区域元素的 和 &#xff0c;该区域由 左上角 (row1, col1) 和 右下角 (row2, col2) 界定。
实现 NumMatrix 类&#xff1a;
NumMatrix(int[][] matrix) 用整数矩阵 matrix 初始化对象。
void update(int row, int col, int val) 更新 matrix[row][col] 的值到 val 。
int sumRegion(int row1, int col1, int row2, int col2) 返回矩阵 matrix 中指定矩形区域元素的 和 &#xff0c;该区域由 左上角 (row1, col1) 和 右下角 (row2, col2) 界定。
来源&#xff1a;力扣&#xff08;LeetCode&#xff09;
链接&#xff1a;https://leetcode-cn.com/problems/range-sum-query-2d-mutable
一维线段树运用二分的思想&#xff0c;将一条线段一分为二&#xff0c;一个结点维护左右两个儿子的信息
二维线段树则是运用四分的思想&#xff0c;横竖两刀&#xff0c;将一个矩形区域分成四份&#xff0c;如同直角坐标系中的四个象限&#xff0c;一个结点维护四个儿子的信息&#xff0c;注意将矩形划分成四份后每个子矩形的坐标&#xff0c;线段树数组记得开16倍
同理&#xff0c;有了这种思想&#xff0c;三维线段树可以八分&#xff0c;四维线段树可以十六分...
class NumMatrix {int t[250 * 250 * 4 * 4 &#43; 5], n, m;
public:void change(int p, int u, int l, int d, int r, int x, int y, int v) {if (u > x || d y || r > 1, my &#61; l &#43; r >> 1;change(p * 4, u, l, mx, my, x, y, v);change(p * 4 &#43; 1, u, my &#43; 1, mx, r, x, y, v);change(p * 4 &#43; 2, mx &#43; 1, l, d, my, x, y, v);change(p * 4 &#43; 3, mx &#43; 1, my &#43; 1, d, r, x, y, v);t[p] &#61; t[p * 4] &#43; t[p * 4 &#43; 1] &#43; t[p * 4 &#43; 2] &#43; t[p * 4 &#43; 3];}}int query(int p, int u, int l, int d, int r, int x1, int y1, int x2, int y2) {if (u > x2 || d y2 || r &#61; x1 && d <&#61; x2 && l >&#61; y1 && r <&#61; y2) {return t[p];} else {int mx &#61; u &#43; d >> 1, my &#61; l &#43; r >> 1;int s1 &#61; query(p * 4, u, l, mx, my, x1, y1, x2, y2);int s2 &#61; query(p * 4 &#43; 1, u, my &#43; 1, mx, r, x1, y1, x2, y2);int s3 &#61; query(p * 4 &#43; 2, mx &#43; 1, l, d, my, x1, y1, x2, y2);int s4 &#61; query(p * 4 &#43; 3, mx &#43; 1, my &#43; 1, d, r, x1, y1, x2, y2);return s1 &#43; s2 &#43; s3 &#43; s4;}}NumMatrix(vector>& matrix) {memset(t, 0, sizeof t);n &#61; matrix.size(), m &#61; matrix[0].size();for (int i &#61; 0; i };