线段树讲解(小进阶)
目录
前言
一、线段树知识回顾
线段树区间加减
区间修改维护:
区间修改的操作:
区间修改update:
线段树的区间查询
区间查询:
区间查询的操作:
递归查询过程:
区间查询query:
代码:
二、线段树的区间修改---乘上一个数’x'
build
区间修改
update
mulpr_update
push_up
代码:
push_down
左:
右:
代码:
区间查询query
代码:
三、例题
例题:P3373 【模板】线段树 2 - 洛谷
编辑
完整代码:
总结
前言
本篇文章主要是根据P3373 【模板】线段树 2 - 洛谷对线段树进行进一步的讲解,因为比较笨拙加上画图耗时大,没有图文搭配讲解,只有纯粹的文字讲解,但是也是非常清楚的,很容易就能理解
一、线段树知识回顾
我们在进一步学习前,先来看一下前置知识
开一个build函数建树,具体操作如下:
1.定义数组:首先,需要定义一个大小为 4n 的数组,其中 n 是线段树的叶子节点数量。这个数组将用于存储线段树的节点信息。
2.构建线段树:一般将线段树按照完全二叉树的形式存储在数组中。假设根节点在数组中的索引是 1,那么对于节点 i,其左子节点为 2i,右子节点为 2i + 1。
3.存储节点信息:每个节点需要保存代表的区间范围和相应的信息,比如区间的最大值、最小值、和等等。在数组中,可以按照某种顺序依次存储这些信息,以便后续的查询和更新操作。
4.建立线段树:通过递归或迭代的方式构建线段树。一般会从叶子节点开始向上构建,通过合并子节点的信息得到父节点的信息,直至构建完整的线段树。
5.查询和更新:通过线段树的结构和数组存储,可以实现高效的区间查询和更新操作。比如,对于查询一个区间的最大值,可以通过递归向下查询到包含目标区间的节点,并根据存储的信息计算出结果。
6.记得注意边界情况:在实现线段树时,需要考虑树的边界情况,比如树的根节点索引是 1,叶子节点索引从 n+1 开始等,以确保正确地访问和操作节点。
// 建树函数
void build(LL l, LL r, LL fa) {if (l == r) { // 如果区间只有一个元素t[fa] = a[l] % m; // 直接赋值return;}LL mid = (l + r) >> 1; // 计算中间节点build(l, mid, fa << 1); // 递归构建左子树build(mid + 1, r, fa << 1 | 1); // 递归构建右子树push_up(fa); // 更新父节点
}
线段树区间加减
区间修改维护:
1.需要修改线段树中某个特定区间的值时,可以通过递归的方式向下更新区间。
2.如果要修改的区间与当前节点表示的区间没有交集,则无需修改该节点。
3.如果要修改的区间完全包含当前节点的区间,则直接更新当前节点的信息,并将修改操作下传给子节点。
4.如果要修改的区间与当前节点的区间部分相交,则需要先将当前节点的信息更新,然后将修改操作同时下传给左右子节点。
区间修改的操作:
1.区间修改的操作通常包括加法、减法、赋值等。
2.当需要对区间内的每个元素进行相同的修改时,可以利用线段树的特性进行高效操作。
3.在修改区间时,需要根据当前节点的区间范围、待修改区间和修改方式来确定如何操作当前节点和其子节点。
递归更新过程:
从线段树的根节点开始递归向下更新,直到找到包含待修改区间的叶子节点。
在递归过程中根据节点的区间范围和待修改区间的关系,决定如何更新节点的信息并向下传递修改操作。
此外,对于区间操作,我们考虑引入一个名叫“ lazy tag ”(懒标记)的东西——之所以称其“lazy”,是因为原本区间修改需要通过先改变叶子节点的值,然后不断地向上递归修改祖先节点直至到达根节点,时间复杂度最高可以到达 O(nlogn) 的级别。但当我们引入了懒标记之后,区间更新的期望复杂度就降到了 O(logn) 的级别且甚至会更低。
因此,我们再弄一个tag数组,大小也是4*N
区间修改update:
void psuh_up(LL fa) {t[fa] = t[fa << 1] + t[fa << 1 | 1];//向上不断维护父节点
}
void push_down(LL l,LL r,LL fa) {LL mid = (l + r) >> 1;t[fa << 1] += tag[fa] * (mid - l + 1);tag[fa << 1] += tag[fa];t[fa << 1|1] += tag[fa] * (r-mid);tag[fa << 1|1] += tag[fa];tag[fa] = 0;// //每次将懒惰标识下放到两个儿子节点,自身置为0,以此不断向下传递
}
void update(LL ql, LL qr, LL l, LL r, LL k, LL fa) {if (ql <= l && qr >= r) //如果区间被包含,直接返回该节点的懒惰标识{t[fa] +=k * (r - l + 1);tag[fa] += k;return;}LL mid = (l + r) >> 1;push_down(l, r, fa);//下放懒惰标识if (ql <= mid)update(ql, qr, l, mid,k, fa << 1);//朝左边下放if (qr > mid)update(ql, qr, mid + 1, r,k, fa << 1 | 1);//右边psuh_up(fa);//再将修改后的值向上返回,维护父节点
}
我们这一期会对update和push_down进行更改
线段树的区间查询
-
区间查询:
- 当需要查询线段树中某个特定区间的信息时,可以通过递归的方式向下查询区间。
- 如果要查询的区间与当前节点表示的区间没有交集,则无需查询该节点,直接返回默认值(如0或无穷大)。
- 如果要查询的区间完全包含当前节点的区间,则直接返回该节点存储的信息。
- 如果要查询的区间与当前节点的区间部分相交,则需要同时查询左右子节点,并根据查询结果合并得到最终结果。
-
区间查询的操作:
- 区间查询的操作通常包括求和、求最大值、求最小值等。
- 在查询区间时,需要根据当前节点的区间范围、待查询区间和查询方式来确定如何操作当前节点和其子节点。
-
递归查询过程:
- 从线段树的根节点开始递归向下查询,直到找到包含待查询区间的叶子节点。
- 在递归过程中根据节点的区间范围和待查询区间的关系,决定如何查询节点的信息并向下传递查询操作。
- 最终将所有查询结果合并得到最终的区间查询结果。
通过以上方法,可以实现对线段树中特定区间的查询操作。线段树区间查询是线段树的一个重要功能,能够快速有效地获取区间内的信息,提高了区间查询的效率。
区间查询query:
LL query(LL ql, LL qr, LL l, LL r, LL fa) {LL ret = 0;if (ql <= l && qr >= r) 如果区间被包含,直接返回该节点的懒惰标识{return t[fa];}LL mid = (l + r) >> 1;push_down(l, r, fa);//没有被包含,下放任务if (ql <= mid)ret += query(ql, qr, l, mid, fa << 1);if (qr > mid)ret += query(ql, qr, mid + 1, r, fa << 1|1);//在查询范围的左区间和右区间的值相加并返回return ret;
}
代码:
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
typedef long long LL;
LL n, m, t[N * 4], tag[N * 4], a[N];
void psuh_up(LL fa) {t[fa] = t[fa << 1] + t[fa << 1 | 1];//向上不断维护父节点
}
void push_down(LL l,LL r,LL fa) {LL mid = (l + r) >> 1;t[fa << 1] += tag[fa] * (mid - l + 1);tag[fa << 1] += tag[fa];t[fa << 1|1] += tag[fa] * (r-mid);tag[fa << 1|1] += tag[fa];tag[fa] = 0;// //每次将懒惰标识下放到两个儿子节点,自身置为0,以此不断向下传递
}
LL query(LL ql, LL qr, LL l, LL r, LL fa) {LL ret = 0;if (ql <= l && qr >= r) 如果区间被包含,直接返回该节点的懒惰标识{return t[fa];}LL mid = (l + r) >> 1;push_down(l, r, fa);//没有被包含,下放任务if (ql <= mid)ret += query(ql, qr, l, mid, fa << 1);if (qr > mid)ret += query(ql, qr, mid + 1, r, fa << 1|1);//在查询范围的左区间和右区间的值相加并返回return ret;
}
void update(LL ql, LL qr, LL l, LL r, LL k, LL fa) {if (ql <= l && qr >= r) //如果区间被包含,更新懒惰标识并返回{t[fa] +=k * (r - l + 1);tag[fa] += k;return;}LL mid = (l + r) >> 1;push_down(l, r, fa);//下放懒惰标识if (ql <= mid)update(ql, qr, l, mid,k, fa << 1);//朝左边下放if (qr > mid)update(ql, qr, mid + 1, r,k, fa << 1 | 1);//右边psuh_up(fa);//再将修改后的值向上返回,维护父节点
}
void build(LL l, LL r, LL fa) {if (l == r) // //如果左右区间相同,那么必然是叶子节,只有叶子节点是被真实赋值的{t[fa] = a[l];return;}LL mid = (l + r) >> 1;build(l, mid, fa << 1);build(mid + 1, r, fa << 1 | 1);//使用二分来优化psuh_up(fa);//此处由于我们是要通过子节点来维护父节点,所以push_up的位置应当是在回溯时将子节点的值取和交给父节点
}
int main() {cin >> n >> m;for (int i = 1; i <= n; i++)cin >> a[i];build(1, n, 1);while (m--) {int op; cin >> op;if (op == 1) {LL x, y, k; cin >> x >> y >> k;update(x, y, 1, n, k, 1);}else if(op==2){LL x, y;cin >> x >> y;cout << query(x, y, 1, n, 1) << endl;}}return 0;
}
二、线段树的区间修改---乘上一个数’x'
老样子,先看题目

根据题目意思先建树
build:
代码:
// 建树函数
void build(LL l, LL r, LL fa) {if (l == r) { // 如果区间只有一个元素t[fa] = a[l] % m; // 直接赋值return;}LL mid = (l + r) >> 1; // 计算中间节点build(l, mid, fa << 1); // 递归构建左子树build(mid + 1, r, fa << 1 | 1); // 递归构建右子树push_up(fa); // 更新父节点
}
因为题目增加了一个区间乘一个数,所以我们需要维护两个tag数组,tag1,tag2,大小都是n*4;
令tag1为区间乘一个数的数组,由于区间乘一个数,所以数组tag1全部初始化为1;
代码:
int main() {cin >> n >>q>> m;for (int i = 0; i <= N * 4; i++)tag1[i] = 1;for (int i = 1; i <= n; i++)cin >> a[i];build(1, n, 1);while (q--) {int op; cin >> op;if (op == 2) {LL x, y, k; cin >> x >> y >> k;update(x, y, 1, n, 1, k%m);}else if (op == 3) {LL x, y; cin >> x >> y;cout << query(x, y, 1, n, 1)%m << endl;}else if (op == 1) {LL x, y, k; cin >> x >> y >> k;mulpr_update(x, y, 1, n, 1, k);}}return 0;
}
这个模去m是题目要求的,后面不会去详细讲,只会说tag数组如何维护以及query的一点改动;
区间修改
需要两个不同的update来维护区间加和区间乘
区间加就不多赘述了
update
// 更新函数
void update(LL ql, LL qr, LL l, LL r, LL fa, LL k) {if (ql <= l && qr >= r) { // 如果更新区间完全覆盖当前区间t[fa] = (t[fa] + (r - l + 1) * k) % m; // 更新当前节点的值tag2[fa] = (tag2[fa] + k) % m; // 更新加法标记return;}LL mid = (l + r) >> 1; // 计算中间节点push_down(l, r, fa); // 向下更新标记if (ql <= mid) // 如果更新区间在左子树update(ql, qr, l, mid, fa << 1, k); // 更新左子树if (qr > mid) // 如果更新区间在右子树update(ql, qr, mid + 1, r, fa << 1 | 1, k); // 更新右子树push_up(fa); // 更新父节点
}
来看一下区间乘
如果要更新的区间覆盖了当前的区间,直接更新当前t数组的值,更新tag1,tag2的懒惰标识,然后return,就不需要下放懒惰标识了;
如果区间没有覆盖,puah_down下放懒惰标识,更新左边,然后更新右边,然后push_up向上更新父节点;
mulpr_update
// 乘法更新函数
void mulpr_update(LL ql, LL qr, LL l, LL r, LL fa, LL k) {if (ql <= l && qr >= r) { // 如果更新区间完全覆盖当前区间t[fa] = t[fa] * k % m; // 更新当前节点的值tag1[fa] = tag1[fa] * k % m; // 更新乘法标记tag2[fa] = tag2[fa] * k % m; // 更新加法标记return;}LL mid = (l + r) >> 1; // 计算中间节点push_down(l, r, fa); // 向下更新标记if (ql <= mid) // 如果更新区间在左子树mulpr_update(ql, qr, l, mid, fa << 1, k); // 更新左子树if (qr > mid) // 如果更新区间在右子树mulpr_update(ql, qr, mid + 1, r, fa << 1 | 1, k); // 更新右子树push_up(fa); // 更新父节点
}
push_up
代码:
// 向上更新函数,更新父节点的值
void push_up(LL fa) {// 父节点的值等于左右子节点的和,取模 mt[fa] = (t[fa << 1] + t[fa << 1 | 1]) % m;
}
push_down
比较有难度的一个push_down,如果思路清晰的话就会变得很简单
左:
先将需要下放懒惰标识的区间取mid,更新树t左子节点,用tag1和tag2 fa位置的懒惰值更新
然后更新tag1左子节点,因为是乘,所以将tag1fa父节点的懒惰标识乘上tag1[fa<<1]左子节点的懒惰标识更新该左子节点的懒惰标识
然后更新tag2左子节点,虽然是区间加的懒惰数组,但是tag1和tag2作用在同一个线段树,所以在更新tag2时需要看看tag1[fa]有没有懒惰标识,有的话得加上tag1[fa] * tag2[fa << 1],即如果tag1有懒惰标识,将其乘上tag2左子节点[fa<<1]原本有的懒惰标识;
右:
更新树t右子节点,用tag1和tag2 fa位置的懒惰值更新
然后更新tag1右子节点,因为是乘,所以将tag1fa父节点的懒惰标识乘上tag1[fa<<1|1]右子节点的懒惰标识更新该左子节点的懒惰标识
然后更新tag2右子节点,虽然是区间加的懒惰数组,但是tag1和tag2作用在同一个线段树,所以在更新tag2时需要看看tag1[fa]有没有懒惰标识,有的话得加上tag1[fa] * tag2[fa << 1|1],即如果tag1有懒惰标识,将其乘上tag2左子节点[fa<<1|1]原本有的懒惰标识;
代码:
// 向下更新函数,处理懒惰标记
void push_down(LL l, LL r, LL fa) {LL mid = (l + r) >> 1; // 计算中间节点// 更新左子节点t[fa << 1] = (tag1[fa] * t[fa << 1] % m + tag2[fa] * (mid - l + 1) % m) % m;tag1[fa << 1] = (tag1[fa << 1] * tag1[fa]) % m; // 更新乘法标记tag2[fa << 1] = (tag2[fa] + tag1[fa] * tag2[fa << 1] % m) % m; // 更新加法标记// 更新右子节点t[fa << 1 | 1] = (tag1[fa] * t[fa << 1 | 1] % m + (tag2[fa] * (r - mid)) % m) % m;tag1[fa << 1 | 1] = (tag1[fa << 1 | 1] * tag1[fa]) % m; // 更新乘法标记tag2[fa << 1 | 1] = (tag2[fa] + tag1[fa] * tag2[fa << 1 | 1] % m) % m; // 更新加法标记// 清空当前节点的标记tag1[fa] = 1;tag2[fa] = 0;
}
区间查询query
代码:
// 查询函数
LL query(LL ql, LL qr, LL l, LL r, LL fa) {LL ret = 0; // 初始化返回值if (ql <= l && qr >= r) { // 如果查询区间完全覆盖当前区间return t[fa] % m; // 返回当前节点的值}LL mid = (l + r) >> 1; // 计算中间节点push_down(l, r, fa); // 向下更新标记if (ql <= mid) // 如果查询区间在左子树ret = (ret + query(ql, qr, l, mid, fa << 1)) % m; // 查询左子树if (qr > mid) // 如果查询区间在右子树ret = (ret + query(ql, qr, mid + 1, r, fa << 1 | 1)) % m; // 查询右子树return ret % m; // 返回结果
}
三、例题
例题:P3373 【模板】线段树 2 - 洛谷

完整代码:
#include <iostream>
#include <cstring>
using namespace std;// 定义常量 N,表示数组的最大大小
const int N = 1e5 + 10;// 定义长整型别名 LL
typedef long long LL;// 全局变量
LL n, m, q; // n: 数组大小, m: 模数, q: 查询次数
LL t[N * 4], a[N]; // t: 线段树数组, a: 原始数组
LL tag1[N * 4], tag2[N * 4]; // tag1: 乘法标记, tag2: 加法标记// 向上更新函数,更新父节点的值
void push_up(LL fa) {// 父节点的值等于左右子节点的和,取模 mt[fa] = (t[fa << 1] + t[fa << 1 | 1]) % m;
}// 向下更新函数,处理懒惰标记
void push_down(LL l, LL r, LL fa) {LL mid = (l + r) >> 1; // 计算中间节点// 更新左子节点t[fa << 1] = (tag1[fa] * t[fa << 1] % m + tag2[fa] * (mid - l + 1) % m) % m;tag1[fa << 1] = (tag1[fa << 1] * tag1[fa]) % m; // 更新乘法标记tag2[fa << 1] = (tag2[fa] + tag1[fa] * tag2[fa << 1] % m) % m; // 更新加法标记// 更新右子节点t[fa << 1 | 1] = (tag1[fa] * t[fa << 1 | 1] % m + (tag2[fa] * (r - mid)) % m) % m;tag1[fa << 1 | 1] = (tag1[fa << 1 | 1] * tag1[fa]) % m; // 更新乘法标记tag2[fa << 1 | 1] = (tag2[fa] + tag1[fa] * tag2[fa << 1 | 1] % m) % m; // 更新加法标记// 清空当前节点的标记tag1[fa] = 1; tag2[fa] = 0;
}// 建树函数
void build(LL l, LL r, LL fa) {if (l == r) { // 如果区间只有一个元素t[fa] = a[l] % m; // 直接赋值return;}LL mid = (l + r) >> 1; // 计算中间节点build(l, mid, fa << 1); // 递归构建左子树build(mid + 1, r, fa << 1 | 1); // 递归构建右子树push_up(fa); // 更新父节点
}// 查询函数
LL query(LL ql, LL qr, LL l, LL r, LL fa) {LL ret = 0; // 初始化返回值if (ql <= l && qr >= r) { // 如果查询区间完全覆盖当前区间return t[fa] % m; // 返回当前节点的值}LL mid = (l + r) >> 1; // 计算中间节点push_down(l, r, fa); // 向下更新标记if (ql <= mid) // 如果查询区间在左子树ret = (ret + query(ql, qr, l, mid, fa << 1)) % m; // 查询左子树if (qr > mid) // 如果查询区间在右子树ret = (ret + query(ql, qr, mid + 1, r, fa << 1 | 1)) % m; // 查询右子树return ret % m; // 返回结果
}// 更新函数
void update(LL ql, LL qr, LL l, LL r, LL fa, LL k) {if (ql <= l && qr >= r) { // 如果更新区间完全覆盖当前区间t[fa] = (t[fa] + (r - l + 1) * k) % m; // 更新当前节点的值tag2[fa] = (tag2[fa] + k) % m; // 更新加法标记return;}LL mid = (l + r) >> 1; // 计算中间节点push_down(l, r, fa); // 向下更新标记if (ql <= mid) // 如果更新区间在左子树update(ql, qr, l, mid, fa << 1, k); // 更新左子树if (qr > mid) // 如果更新区间在右子树update(ql, qr, mid + 1, r, fa << 1 | 1, k); // 更新右子树push_up(fa); // 更新父节点
}// 乘法更新函数
void mulpr_update(LL ql, LL qr, LL l, LL r, LL fa, LL k) {if (ql <= l && qr >= r) { // 如果更新区间完全覆盖当前区间t[fa] = t[fa] * k % m; // 更新当前节点的值tag1[fa] = tag1[fa] * k % m; // 更新乘法标记tag2[fa] = tag2[fa] * k % m; // 更新加法标记return;}LL mid = (l + r) >> 1; // 计算中间节点push_down(l, r, fa); // 向下更新标记if (ql <= mid) // 如果更新区间在左子树mulpr_update(ql, qr, l, mid, fa << 1, k); // 更新左子树if (qr > mid) // 如果更新区间在右子树mulpr_update(ql, qr, mid + 1, r, fa << 1 | 1, k); // 更新右子树push_up(fa); // 更新父节点
}// 主函数
int main() {cin >> n >> q >> m; // 输入数组大小 n, 查询次数 q, 模数 mfor (int i = 0; i <= N * 4; i++) tag1[i] = 1; // 初始化乘法标记为 1for (int i = 1; i <= n; i++) cin >> a[i]; // 输入数组元素build(1, n, 1); // 构建线段树while (q--) { // 处理每个查询int op; cin >> op; // 输入操作类型if (op == 2) { // 加法更新操作LL x, y, k; cin >> x >> y >> k; // 输入区间 [x, y] 和加数 kupdate(x, y, 1, n, 1, k % m); // 执行加法更新}else if (op == 3) { // 查询操作LL x, y; cin >> x >> y; // 输入查询区间 [x, y]cout << query(x, y, 1, n, 1) % m << endl; // 输出查询结果}else if (op == 1) { // 乘法更新操作LL x, y, k; cin >> x >> y >> k; // 输入区间 [x, y] 和乘数 kmulpr_update(x, y, 1, n, 1, k); // 执行乘法更新}}return 0; // 程序结束
}

总结
本期关于线段树的讲解就到这里,有什么疑问或者有什么错误的地方欢迎大家一起交流学习,下期带来线段树的离散化,二分搜索等进阶内容
相关文章:
线段树讲解(小进阶)
目录 前言 一、线段树知识回顾 线段树区间加减 区间修改维护: 区间修改的操作: 区间修改update: 线段树的区间查询 区间查询: 区间查询的操作: 递归查询过程: 区间查询query: 代码&…...
4082P 信号/频谱分析仪
——新利通仪器仪表—— 4082P丨信号/频谱分析仪 2Hz~110GHz Ceyear 4082系列信号/频谱分析仪在显示平均噪声电平、相位噪声、互调抑制、动态范围、幅度精度和测试速度等方面具备极佳的射频性能。具备强大的频谱分析、符合标准的功率测量套件、I/Q分析、瞬态分析…...
夏季跑步注意
夏季跑步注意 医学专家警示:大众跑者需以安全为先,警惕高温环境下“盲目冲刺”的风险。一些事件再次印证马拉松适宜气温为6-15℃,超过20℃时需主动降速并增加补水量。 所以建议每一位跑友,为了健康的跑步,每年除了做…...
openharmony5.0.0中C++公共基础类测试-线程相关(一)
C公共基础类测试及源码剖析 延续传统,show me the code,除了给出应用示例还重点分析了下openharmony中的实现。 简介 openharmony中提供了C公共基础类库,为标准系统提供了一些常用的C开发工具类,本文分析其实现,并给…...
TDengine 数据订阅设计
简介 数据订阅作为 TDengine 的一个核心功能,为用户提供了灵活获取所需数据的能力。通过深入了解其内部原理,用户可以更加有效地利用这一功能,满足各种实时数据处理和监控需求。 基本概念 主题 与 Kafka 一样,使用 TDengine 数…...
python:mido 提取 midi文件中某一音轨的音乐数据
pip install mido 使用 mido库可以方便地处理 MIDI 文件,提取其中音轨的音乐数据。 1.下面的程序会读取指定的 MIDI 文件,并提取指定编号音轨的音乐数据,主要包括音符事件等信息。 编写 mido_extract.py 如下 # -*- coding: utf-8 -*- &…...
vue3 中推荐使用的页面布局方式
1、Flexbox布局 原理 Flexbox(弹性盒子布局模型)提供了一种更加高效的方式来对容器中的子元素进行布局、对齐和分配空间。它能够根据容器的大小和子元素的内容自动调整布局,非常适合一维布局(水平或垂直方向)。 优…...
URP-UGUI交互功能实现
一、非代码层面实现交互(SetActive) Button :在OnClick()中添加SetActive方法(但是此时只首次有效) Toggle :在OnClick()中添加动态的SetActive方法 &#…...
UniGoal 具身导航 | 通用零样本目标导航 CVPR 2025
UniGoal的提出了一个通用的零样本目标导航框架,能够统一处理多种类型的导航任务 (如对象类别导航、实例图像目标导航和文本目标导航),而无需针对特定任务进行训练或微调。 它的特点是 图匹配与多阶段探索策略!&#x…...
通过Quartus II实现Nios II编程
目录 一、认识Nios II二、使用Quartus II 18.0Lite搭建Nios II硬件部分三、软件部分四、运行项目 一、认识Nios II Nios II软核处理器简介 Nios II是Altera公司推出的一款32位RISC嵌入式处理器,专门设计用于在FPGA上运行。作为软核处理器,Nios II可以通…...
Linux/AndroidOS中进程间的通信线程间的同步 - IPC方式简介
前言 从来没有总结过Linux/Android系统中进程间的通信方式和线程间的同步方式,这个专栏就系统总结讨论一下。首先从标题可知,讨论问题的主体是进程和线程、通信和同步;在这里默认你理解进程和线程的区别。通信和同步有什么概念上的区别&…...
Windows:注册表配置应用
0、简介 本篇博客记录一下,日常的系统注册表配置选项,以防再次遇到问题不知如何解决。 1、开机启动配置 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run :: 此位置存储了所有用户登录时需要启动的程序。 在该项下新建字符串值&#…...
升级xcode16之后react-native-zip-archive不兼容,unsupported option ‘-G‘
问题 升级xcode到16之后,xcode build报错:unsupported option -G for target x86_64-apple-ios13.4-simulator (in target RNZipArchive from project Pods) 出现原因 在 React Native 项目中,当你将 Xcode 升级到 16 后,可能会遇到 RNZipArchive 相关的编译错误,特别是…...
WebXR教学 05 项目3 太空飞船小游戏
准备工作 自动创建 package.json 文件 npm init -y 安装Three.js 3D 图形库,安装现代前端构建工具Vite(用于开发/打包) npm install three vite 启动 Vite 开发服务器(推荐)(正式项目开发) …...
网页在浏览器中显示的原理(简要)
网页在浏览器中显示的过程是一个复杂的多阶段流程。 1. 输入URL并发起请求 用户在地址栏输入URL并回车 浏览器检查缓存(DNS缓存、页面缓存等) 如果没有缓存,通过DNS解析获取服务器IP地址 建立TCP连接(三次握手) 发…...
rl中,GRPO损失函数详解。
文章目录 **一、GRPO损失函数的设计背景****二、代码逐行解析****三、关键组件详解****1. 对数概率与KL散度计算****2. 优势值与策略梯度****3. 掩码与平均损失****四、训练动态与调参建议**在TRL(Transformer Reinforcement Learning)库中,GRPO(Group Relative Policy Opt…...
【Java面试笔记:基础】12.Java有几种文件拷贝方式?哪一种最高效?
在 Java 中,文件拷贝可以通过多种方式实现,不同方式的性能和适用场景有所差异。 1. Java 文件拷贝方式 传统 IO 方式 使用 FileInputStream 和 FileOutputStream,通过循环读取和写入数据实现文件拷贝。 示例代码: try (InputStream is = new FileInputStream("sou…...
【leetcode】3524 求出数组的X值1
题目链接 题目描述 给你一个正整数数组 nums 和一个正整数 k。 你可以对数组执行一次操作:移除不重叠的前缀和后缀(可以为空),留下一个连续非空子数组。 对于每一种留下的子数组,计算: (该子数组的乘积…...
达梦统计信息收集情况检查
查询达梦某个对象上是否有统计信息 select id,T_TOTAL,N_SMAPLE,N_DISTINCT,N_NULL,BLEVEL,N_LEAF_PAGES,N_LEAF_USED_PAGES,LAST_GATHERED from sysstats where id IN (select id from sysobjects where upper(name)upper(&objname));可能有系统对象,可以增加…...
1️⃣5️⃣three.js_GUI辅助调试器
15、GUI辅助调试器 3D虚拟工厂在线体验 GUI辅助调试器将原本需要修改代码调整参数并刷新页面的操作,简化为直接在GUI中实时调整,实现所见即所得的效果。 导入GUI 库 //引入GUI辅助调试器 import {GUI } from three/addons/libs/lil-gui.module.min.js创建GUI辅助调试器对象 c…...
【matlab】气泡图的应用
【matlab】气泡图的应用 .rtcContent { padding: 30px; } .lineNode {font-size: 12pt; font-family: "Times New Roman", Menlo, Monaco, Consolas, "Courier New", monospace; font-style: normal; font-weight: normal; } clear load zb_equi.mat load …...
@Configuration注解对应实现implements WebMvcConfigurer的配置不生效问题。
检查项目是否有其他配置实现了 extends WebMvcConfigurationSupport,如果有就是这个配置导致实现implements WebMvcConfigurer的配置不生效。 我的问题项目有imgconfig,和webconfig Configuration public class ImgConfig extends WebMvcConfigurationS…...
飞帆控件:在编辑模式下额外加载的库
飞帆是一个自由的控件设计平台。在飞帆中,我们可以很方便地创建基于 Vue 2 组件的控件,并使用控件来搭建网页。 他山之石,可以攻玉。在创建控件中,使用 js 、css 依赖库能让我们的控件更强大。 有些时候,在编辑模式下…...
【k8s】docker、k8s、虚拟机的区别以及使用场景
一、Docker (一)概念 Docker 是一个开源的应用容器引擎,允许开发者将应用及其依赖打包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可实现虚拟化。 (二)隔离性 Docker 的隔离…...
Super-Vlan和MUX-Vlan的原理、配置、区别
Super-Vlan 原理 Super-Vlan也叫Aggregate-Vlan。 一般的三层交换机中,通常是采用一个VLAN对应一个vlanif接口的方式实现广播域之间的互通,这在某些情况下导致了IP地址的浪费。因为一个VLAN对应的子网中,子网号、子网定向广播地址、子网缺…...
Docker容器化技术全栈指南:从基础运维到企业级实践
Docker容器化技术全栈指南:从基础运维到企业级实践 一、Docker核心价值与日常运维全景 1. 容器化革命性优势 维度传统虚拟化Docker容器启动速度分钟级(完整OS引导)秒级(共享内核)资源消耗每个VM需独立OS(…...
Python 赋能区块链教育:打造去中心化学习平台
Python 赋能区块链教育:打造去中心化学习平台 引言 区块链技术正在重塑全球多个行业,而教育领域也不例外。传统的在线学习平台往往依赖中心化存储和管理模式,导致数据安全、用户隐私、资源共享等问题难以解决。而随着 Web 3.0 的发展,区块链在教育场景中的应用逐渐受到关…...
el-table怎么显示 特殊单元格的值
1. 在 el-table-column 上绑定了 formatter 方法 formatEntityName ,它会对每一行该列的数据( cellValue )进行处理。 2. 在 formatEntityName 方法中,尝试对传入的 cellValue 进行 JSON.parse 操作,并根…...
Java中实现单例模式的多种方法:原理、实践与优化
单例模式(Singleton Pattern)是设计模式中最简单且最常用的模式之一,旨在确保一个类只有一个实例,并提供全局访问点。在 Java 开发中,单例模式广泛应用于配置管理、日志记录、数据库连接池和线程池等场景。然而&#x…...
2025-04-23 Python深度学习3——Tensor
文章目录 1 张量1.1 数学定义1.2 PyTorch中的张量 2 创建 Tensor2.1 直接创建**torch.tensor()****torch.from_numpy()** 2.2 依据数值创建**torch.zeros() / torch.zeros_like()****torch.ones() / torch.ones_like()****torch.full() / torch.full_like()****torch.arange() …...

