树链剖分详解,看这一篇就够了

前置知识:

  • 树形结构
  • 链式前向星(熟练)
  • 线段树(熟练)
  • DFS序(熟练)
  • LCA(了解定义)

什么是树链剖分

树链剖分其实有两种:重链剖分和长链剖分。重链剖分就是把儿子节点最重的儿子称为重儿子,把树分成若干条重链(如图一);

图一
图一

 长链剖分则是把深度差最大的儿子称为长儿子,把树分成若干条长链(如图二):

图二

 树链剖分的应用非常广泛,一般用的都是重链剖分。

树链剖分是提高树上搜索效率的一个巧妙方法,它一定规则把树剖分成一条线性的不相交的链,对整棵树的操作,就转化为对链的操作;而从根到任何一条链只是经过\Theta (\log _2n)条链从而操作的复杂度为\Theta (\log _2n)

树链剖分的一个特别之处,就是每条链的 DFS序 是有序的可以使用线段树处理,从而高效地解决一些树上的修改和查询问题。

树链剖分和LCA

首先通过求最近公共祖先介绍树链剖分的基本概念,而且进行树链剖分时求 LCA 是必需的步骤。

LCA 的概念

  • LCA问题:在一棵有根树中,一个节点的祖先节点是指它本身或者它父节点的祖先。给定两个节点,两个点共同的祖先中距离两者最近的节点就是这两个节点的最近公共祖先。需要注意的是最近公共祖先可能是这两个节点中的某一个。
  • 求LCA的各种算法都是快速向上“跳”到祖先节点。回顾求LCA的两种方法,其思想可以概括为:①倍增法,用二进制递增直接向祖先“跳”;②Tarjan算法,用并查集合并子树,子树内的节点都指向子树的根,查询LCA时,可以从节点直接跳到它所在的子树的根,从而实现快速跳的目的。

树链剖分的基本概念:

  1. 重儿子:假设x有n个儿子节点,其中以3儿子节点的为根子树大小最大,3就是x的重儿子
  2. 轻儿子:除重儿子外的所有儿子均为轻儿子
  3. 以图三为例:1的重儿子为3,轻儿子为2;3的重儿子为6,其余的为轻儿子
  4. 轻边:x与轻儿子相连的边
  5. 重边:x与重儿子相连的边
  6. 轻链:均由轻儿子构成的一条链
  7. 重链:均由重儿子构成的一条链
图三

 

进行树链剖分时,求 LCA也是必需的步骤。 和倍增法很像,树链剖分也是“跳”到祖先节点,它的跳法比较巧妙。每条链路内的节点可以看作一个集合,并以“链头”为集;链路上的节点查询LCA时,都指向链头,从而实现快速跳的目的。特别关键的是,从根到叶子只需要经过\Theta (\log _2n)条链,那么从一个节点跳到它的LCA,只需要跳\Theta (\log _2n)条链。

如何把树剖成链,使从根到叶子经过的链更少?注意每个节点只能属于一条链。很自然的思路是观察树上节点的分布情况,如果选择那些有更多节点的分支建链,链会更长一些,从而使链的数量更少。如图四所示,图四从根节点a开始,每次选择有更多子节点的分支建链,最后形成了粗线条所示的3条链。从叶子节点到根,最多经过两条链。例如,从 h 到 a,先经过以 d 为头的链,然后就到了以 a 为头的链。

预处理节点信息


我们需要的信息如下

  • dep[X]:x节点的深度
  • fa[X]:x节点的父亲节点
  • son[X]:x节点的重儿子
  • siz[X]:x节点为根的子树大小
  • top[X]:x节点所在链的顶点

首先第一个DFS我们直接获取 dep[X],fa[X],son[X],siz[X]

void dfs1(int x) {siz[x] = 1;dep[x] = dep[f[x]] + 1;for (int i = head[x]; i; i = e[i].ne) {int dd = e[i].to;if (dd == f[x])continue;f[dd] = x;dfs1(dd);siz[x] += siz[dd];if (!son[x] || siz[son[x]] < siz[dd])son[x] = dd;}
}

接下来获取top[X]

我们处理的方式:优先对重儿子处理,重儿子处理结束后再处理轻儿子(新开链)

void dfs2(int x, int tv) {top[x] = tv;if (son[x])dfs2(son[x], tv);for (int i = head[x]; i; i = e[i].ne) {int dd = e[i].to;if (dd == f[x] || dd == son[x])continue;dfs2(dd, dd);}
}

现在,我们按照倍增法求LCA的思路推导,看看能不能转化到树链剖分上。

经过剖分得到重链后,该怎么求 x,y 的LCA呢?有两种情况:

  1. 当两个节点在同一条重链上的时候。重链上的节点都是祖先和后代的关系,所以位置就在深度最浅的那个节点上。
  2. x和y不在同一条重链上。让x和y沿着这一条重链向上条,直到位于同一条重链,此时直接向上跳即可。

好了,现在我们掌握了精髓,代码如下(是不是很简单?):

for (int i = 1; i <= m; ++i) {int x, y;scanf("%d%d", &x, &y);while (top[x] != top[y]) {if (dep[top[x]] >= dep[top[y]])x = f[top[x]];else y = f[top[y]];}printf("%d\n", dep[x] < dep[y] ? x : y);}

完整代码(洛谷P3379)

//来自于https://www.luogu.com.cn/problem/P3379
#include <cstdio>
#include <iostream>
using namespace std;
struct edge {int to, ne;
} e[1000005];
int n, m, s, ecnt, head[500005], dep[500005], siz[500005], son[500005], top[500005], f[500005];
void add(int x, int y) {e[++ecnt].to = y;e[ecnt].ne = head[x];head[x] = ecnt;
}
void dfs1(int x) {siz[x] = 1;dep[x] = dep[f[x]] + 1;for (int i = head[x]; i; i = e[i].ne) {int dd = e[i].to;if (dd == f[x])continue;f[dd] = x;dfs1(dd);siz[x] += siz[dd];if (!son[x] || siz[son[x]] < siz[dd])son[x] = dd;}
}
void dfs2(int x, int tv) {top[x] = tv;if (son[x])dfs2(son[x], tv);for (int i = head[x]; i; i = e[i].ne) {int dd = e[i].to;if (dd == f[x] || dd == son[x])continue;dfs2(dd, dd);}
}
int main() {scanf("%d%d%d", &n, &m, &s);for (int i = 1; i < n; ++i) {int x, y;scanf("%d%d", &x, &y);add(x, y);add(y, x);}dfs1(s);dfs2(s, s);for (int i = 1; i <= m; ++i) {int x, y;scanf("%d%d", &x, &y);while (top[x] != top[y]) {if (dep[top[x]] >= dep[top[y]])x = f[top[x]];else y = f[top[y]];}printf("%d\n", dep[x] < dep[y] ? x : y);}
}

典型应用

关于重链,还有一个重要特征没有提到:一条重链内部节点的DFS序(时间戳)是连续的。也就是说,如果用DFS序标记这条重链上的节点,那么这条重链就变成一段连续的数字。把这段连续的数字看作“线段”,线段内的区间问题用线段树处理正合适。

根据上述讨论,能够用数据结构(一般是线段树)维护重链,从而高效解决一些树上的问题,如以下问题。

  1. 修改点x到点y的路径上各点的权值。
  2. 查询点x到点y的路径上节点权值之和。
  3. 修改点x子树上各点的权值。
  4. 查询点x子树上所有节点的权值之和。

其中,问题(1)是“树上差分”问题,详见前面的“倍增+差分”解法。树上差分只能解决简单的修改问题,对问题(3)这样的修改整棵子树的问题,树上差分就行不通了。

1.重链的DFS序(时间戳)

前面给出的dfs2()函数,是先DFS重儿子,再DFS轻儿子。如果在dfs2()函数的第1句用编号i d [ x ]记录节点x的DFS序,即id[x] =++num,对每个节点重新编号的结果如图4.50所示。

观察到以下现象。

部节点的编号是有序的。重链{ a , b , e , j , q }的DFS序是1,2,3,4,5;重链d,p的DFS序是7,8;重链c,f的DFS序是10,11

图4.50 重链的DFS序

(2)每棵子树上的所有节点的编号也是有序的。例如,以e为根的子树{ e , i , j , q },其DFS序是3,4,5,6

下面是关键内容-用线段树处理重链。由于每条重链内部的节点是有序的,可以按DFS序把它们安排在一棵线段树上。把每条重链看作一个连续的区间,对一条重链内部的修改和查询,用线段树处理;若一条路径跨越了多条重链,简单地跳过两条重链之间的轻边即可。

提示

重链内部用线段树,重链之间跳过。

如图4.51所示,先建一棵线段树,然后把线段树的节点看作DFS序(时间戳)。DFS序对应了原来那棵树的节点。同一条重链的节点,在线段树上是连续的。

图4.51 用线段树重建树链

2.修改x到y的最短路径上的节点权值

x到y的最短路径经过LCA ( x , y ),这实际上是一个查找LCA ( x , y )的过程。可以借助重链修改路径上的节点权值,步骤如下。

  1. 令x的链头的深度更深,即t o p [ x ] \geq t o p [ y ]。从x开始向上走,先沿着x所在的重链向上走,修改这一段路径上的节点。
  2. 到达x的链头后,跳过一条轻边,到达上一条重链。
  3. 继续执行步骤(1)和步骤(2),直到x和y位于同一条重链上,再修改此时两点之间的节点。

例如,修改从p到q的路径上所有节点权值之和,步骤如下。

  1. 从p走到它的链头t o p [ p ] = d,修改p和d的权值。
  2. 跳到b。
  3. b和q在同一条重链上,修改从b到q的权值。

用线段树处理上述过程,仍以修改从p到q的路径上节点权值之和为例。

  1. 从p跳到链头d,p和d属于同一条重链,用线段树修改对应的[7,8]区间。
  2. 从d穿过轻边(b,d),到达b所在的重链。
  3. b和q在同一条重链上,用线段树修改对应区间[2,5]

3.查询x到y的路径上所有节点权值之和

查询与修改的过程几乎一样,以查询p到q的路径上节点权值之和为例。

  1. 从p跳到链头d,p和d属于同一条重链,用线段树查询对应的[7,8]区间;
  2. 从d穿过轻边(b,d),到达b所在的重链;
  3. b和q在同一条重链上,用线段树查询对应区间[2,5]。

4.修改x的子树上各点的权值,查询x的子树上节点权值之和

每棵子树上的所有节点的DFS序是连续的,也就是说,每棵子树对应了一个连续的区间。

例题——洛谷P3384 轻重链剖分

题目描述

如题,已知一棵包含 NN 个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:

  • 1 x y z,表示将树从 xx 到 yy 结点最短路径上所有节点的值都加上 zz。

  • 2 x y,表示求树从 xx 到 yy 结点最短路径上所有节点的值之和。

  • 3 x z,表示将以 xx 为根节点的子树内所有节点值都加上 zz。

  • 4 x 表示求以 xx 为根节点的子树内所有节点值之和

输入格式

第一行包含 44 个正整数 N,M,R,PN,M,R,P,分别表示树的结点个数、操作个数、根节点序号和取模数(即所有的输出结果均对此取模)。

接下来一行包含 NN 个非负整数,分别依次表示各个节点上初始的数值。

接下来 N-1N−1 行每行包含两个整数 x,yx,y,表示点 xx 和点 yy 之间连有一条边(保证无环且连通)。

接下来 MM 行每行包含若干个正整数,每行表示一个操作。

输出格式

输出包含若干行,分别依次表示每个操作 22 或操作 44 所得的结果(对 PP 取模)。

输入输出样例

输入 #1复制

5 5 2 24
7 3 7 8 0 
1 2
1 5
3 1
4 1
3 4 2
3 2 2
4 5
1 5 1 3
2 1 3

输出 #1复制

2
21

说明/提示

【数据规模】

对于 30\%30% 的数据: 1 \leq N \leq 101≤N≤10,1 \leq M \leq 101≤M≤10;

对于 70\%70% 的数据: 1 \leq N \leq {10}^31≤N≤103,1 \leq M \leq {10}^31≤M≤103;

对于 100\%100% 的数据: 1\le N \leq {10}^51≤N≤105,1\le M \leq {10}^51≤M≤105,1\le R\le N1≤R≤N,1\le P \le 2^{30}1≤P≤230。所有输入的数均在 int 范围内。

【样例说明】

树的结构如下:

各个操作如下:

故输出应依次为 22 和 2121。

代码如下:
//线段树与树链剖分的结合
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#define Rint register int
#define mem(a,b) memset(a,(b),sizeof(a))
#define Temp template<typename T>
using namespace std;
typedef long long LL;
Temp inline void read(T &x){x=0;T w=1,ch=getchar();while(!isdigit(ch)&&ch!='-')ch=getchar();if(ch=='-')w=-1,ch=getchar();while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();x=x*w;
}#define mid ((l+r)>>1)
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define len (r-l+1)const int maxn=200000+10;
int n,m,r,mod;
//见题意 
int e,beg[maxn],nex[maxn],to[maxn],w[maxn],wt[maxn];
//链式前向星数组,w[]、wt[]初始点权数组 
int a[maxn<<2],laz[maxn<<2];
//线段树数组、lazy操作 
int son[maxn],id[maxn],fa[maxn],cnt,dep[maxn],siz[maxn],top[maxn]; 
//son[]重儿子编号,id[]新编号,fa[]父亲节点,cnt dfs_clock/dfs序,dep[]深度,siz[]子树大小,top[]当前链顶端节点 
int res=0;
//查询答案 inline void add(int x,int y){//链式前向星加边 to[++e]=y;nex[e]=beg[x];beg[x]=e;
}
//-------------------------------------- 以下为线段树 
inline void pushdown(int rt,int lenn){laz[rt<<1]+=laz[rt];laz[rt<<1|1]+=laz[rt];a[rt<<1]+=laz[rt]*(lenn-(lenn>>1));a[rt<<1|1]+=laz[rt]*(lenn>>1);a[rt<<1]%=mod;a[rt<<1|1]%=mod;laz[rt]=0;
}inline void build(int rt,int l,int r){if(l==r){a[rt]=wt[l];if(a[rt]>mod)a[rt]%=mod;return;}build(lson);build(rson);a[rt]=(a[rt<<1]+a[rt<<1|1])%mod;
}inline void query(int rt,int l,int r,int L,int R){if(L<=l&&r<=R){res+=a[rt];res%=mod;return;}else{if(laz[rt])pushdown(rt,len);if(L<=mid)query(lson,L,R);if(R>mid)query(rson,L,R);}
}inline void update(int rt,int l,int r,int L,int R,int k){if(L<=l&&r<=R){laz[rt]+=k;a[rt]+=k*len;}else{if(laz[rt])pushdown(rt,len);if(L<=mid)update(lson,L,R,k);if(R>mid)update(rson,L,R,k);a[rt]=(a[rt<<1]+a[rt<<1|1])%mod;}
}
//---------------------------------以上为线段树 
inline int qRange(int x,int y){int ans=0;while(top[x]!=top[y]){//当两个点不在同一条链上 if(dep[top[x]]<dep[top[y]])swap(x,y);//把x点改为所在链顶端的深度更深的那个点res=0;query(1,1,n,id[top[x]],id[x]);//ans加上x点到x所在链顶端 这一段区间的点权和ans+=res;ans%=mod;//按题意取模 x=fa[top[x]];//把x跳到x所在链顶端的那个点的上面一个点}//直到两个点处于一条链上if(dep[x]>dep[y])swap(x,y);//把x点深度更深的那个点res=0;query(1,1,n,id[x],id[y]);//这时再加上此时两个点的区间和即可ans+=res;return ans%mod;
}inline void updRange(int x,int y,int k){//同上 k%=mod;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);update(1,1,n,id[top[x]],id[x],k);x=fa[top[x]];}if(dep[x]>dep[y])swap(x,y);update(1,1,n,id[x],id[y],k);
}inline int qSon(int x){res=0;query(1,1,n,id[x],id[x]+siz[x]-1);//子树区间右端点为id[x]+siz[x]-1 return res;
}inline void updSon(int x,int k){//同上 update(1,1,n,id[x],id[x]+siz[x]-1,k);
}inline void dfs1(int x,int f,int deep){//x当前节点,f父亲,deep深度 dep[x]=deep;//标记每个点的深度 fa[x]=f;//标记每个点的父亲 siz[x]=1;//标记每个非叶子节点的子树大小 int maxson=-1;//记录重儿子的儿子数 for(Rint i=beg[x];i;i=nex[i]){int y=to[i];if(y==f)continue;//若为父亲则continue dfs1(y,x,deep+1);//dfs其儿子 siz[x]+=siz[y];//把它的儿子数加到它身上 if(siz[y]>maxson)son[x]=y,maxson=siz[y];//标记每个非叶子节点的重儿子编号 }
}inline void dfs2(int x,int topf){//x当前节点,topf当前链的最顶端的节点 id[x]=++cnt;//标记每个点的新编号 wt[cnt]=w[x];//把每个点的初始值赋到新编号上来 top[x]=topf;//这个点所在链的顶端 if(!son[x])return;//如果没有儿子则返回 dfs2(son[x],topf);//按先处理重儿子,再处理轻儿子的顺序递归处理 for(Rint i=beg[x];i;i=nex[i]){int y=to[i];if(y==fa[x]||y==son[x])continue;dfs2(y,y);//对于每一个轻儿子都有一条从它自己开始的链 }
}int main(){read(n);read(m);read(r);read(mod);for(Rint i=1;i<=n;i++)read(w[i]);for(Rint i=1;i<n;i++){int a,b;read(a);read(b);add(a,b);add(b,a);}dfs1(r,0,1);dfs2(r,r);build(1,1,n);while(m--){int k,x,y,z;read(k);if(k==1){read(x);read(y);read(z);updRange(x,y,z);}else if(k==2){read(x);read(y);printf("%d\n",qRange(x,y));}else if(k==3){read(x);read(y);updSon(x,y);}else{read(x);printf("%d\n",qSon(x));}}
}

习题 

洛谷上的所有习题icon-default.png?t=N7T8https://www.luogu.com.cn/problem/list?keyword=&tag=228&page=1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1424556.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

算法学习笔记(5.0)-基于比较的高效排序算法-归并排序

##时间复杂度O(nlogn) 目录 ##时间复杂度O(nlogn) ##递归实现归并排序 ##原理 ##图例 ##代码实现 ##非递归实现归并排序 ##释 #代码实现 ##递归实现归并排序 ##原理 是一种基于分治策略的基础排序算法。 1.划分阶段&#xff1a;通过不断递归地将数组从中点处分开&…

尝试使用官方jailhouse-images仓库运行jailhouse

jailhouse 的官方 demo 演示仓库 Demo and testing images: https://github.com/siemens/jailhouse-images 通过jailhouse 的官方 demo 演示仓库&#xff0c;可以直接编译出带有部署有jailhouse程序的Linux镜像&#xff0c;有多个目标平台的Linux镜像可选&#xff0c;也有在qe…

一物一码数字化营销进军调味品行业,五丰黎红“星厨俱乐部”火啦!

近日&#xff0c;由五丰黎红联合纳宝科技精心打造的小程序“星厨俱乐部”火啦&#xff01;一经上线就吸引了大量用户注册和参与&#xff0c;可以说取得了非常成功的市场反馈&#xff0c;那究竟是一个什么样的小程序&#xff0c;竟然有这么大的吸引力呢&#xff1f; 介绍小程序之…

Linux基础之僵尸进程与孤儿进程

目录 一、僵尸进程 1.1 什么是僵尸进程 1.2 为什么要有僵尸状态 1.3 观察我们的僵尸状态 1.4 关于僵尸进程的小Tip 二、孤儿进程 2.1 什么是孤儿进程 一、僵尸进程 1.1 什么是僵尸进程 在上一篇文章中&#xff0c;我们有提到过进程的死亡状态的概念&#xff0c;而我们的…

C#【进阶】委托和事件

委托和事件 文章目录 1、委托1、委托概念2、基本语法3、定义自定义委托4、使用自定义委托5、委托变量可以存储多个函数6、系统定义好的委托思考 怪物死亡数据更新 2、事件1、事件概念2、事件的使用3、为什么有事件思考 热水器 3、匿名函数1、匿名函数概念2、基本语法3、使用4、…

C脚本实现Wincc弹窗重复调用

文章目录 前言一、步骤及解析二、运行画面演示三、总结 前言 在常见的Wincc上位机画面中&#xff0c;点击按钮或控件弹出弹窗&#xff0c;由于不同的弹窗内容不同&#xff0c;变量前缀不同&#xff0c;通常情况下一个弹窗就需要调用一个画面窗口&#xff0c;但画面窗口过多会导…

MySQL存储引擎介绍

查看MySQL数据库中创建表的信息 如上图所示&#xff0c;当我们使用命令show create table server_info\G;可以显示我们所创建的表的信息&#xff0c;只显示两个字段&#xff0c;第一个字段是Table 即是创建的表的名称&#xff0c;第二个字段是Create Table即是创建的表的字段的…

基于Pytorch深度学习神经网络MNIST手写数字识别系统源码(带界面和手写画板)

第一步&#xff1a;准备数据 mnist开源数据集 第二步&#xff1a;搭建模型 我们这里搭建了一个LeNet5网络 参考代码如下&#xff1a; import torch from torch import nnclass Reshape(nn.Module):def forward(self, x):return x.view(-1, 1, 28, 28)class LeNet5(nn.Modul…

Navicat Premium数据库新建函数报错问题

1.问题产生原因&#xff1a; (1)可能是软件 Navicat Premium 的版本不一样 (2)可能是与某些字符集不一样 2.找出解决办法&#xff1a; (1)参考对照系统自带sys数据库表的函数找出的区别&#xff08;后面遇到同样问题可以这样排查&#xff09; (2)不加 DETERMINISTIC 声明&a…

点量云流3D应用线上展厅云推流方案分享

展厅是企业对外展示宣传的窗口&#xff0c;不论企业还是政fu单位、博物馆、科技馆&#xff0c;展厅都可以给用户一个更直观的感受。而随着技术的发展&#xff0c;展厅展示的内容也从最初的图文、视频&#xff0c;扩展更多文件类型&#xff0c;比如PPT\PDF文件以及3D应用数字孪生…

字符串_字符函数和字符串函数

C语言中对字符和字符串的处理很是频繁&#xff0c;但是C语言本身是没有字符串类型的&#xff0c;字符串通常放在常量字符串中或者字符数组中。 字符串常量适用于那些对它不做修改的字符串函数。 目录 1.函数介绍 1.1strlen 1.1.1strlen函数的模拟实现 1.2strcpy 1.2.1st…

OpenAI 重磅发布GPT 4o!可以视频聊天的AI?

OpenAI 重磅发布GPT 4o&#xff01; 前言 就在今日&#xff0c;OpenAI发布了ChatGPT-4o版本&#xff0c;技术主管 Mira Murati 在直播中表示GPT-4o对比之前版本速度更快&#xff0c;在文本、视频和音频方面的能力也都有所提高。值得注意的是它还可以让用户与 ChatGPT 进行视频聊…

C++学习一(主要对cin的理解)

#include<iostream> int main() {int sum 0, value 0;//读取数据直到遇到文件尾&#xff0c;计算所有读入的值的和while (std::cin >> value){ //等价于sumsumvaluesum value;}std::cout << "Sum is :" << sum << std::endl;sum …

Java—字节码文件解读

原文 public class ClassIntrucation {public static void main(String[] args) {int i 10;int j i;j;j;} } 查看字节码文件命令 javap -c 字节码文件例如&#xff1a; javap -c ClassIntrucation 结果 public class ClassIntrucation {public ClassIntrucation();Code:…

怎么把3d模型导出cad立面---模大狮模型网

在设计工作中&#xff0c;将3D模型导出到CAD软件并生成立面图是一项常见但关键的任务。这不仅有助于更好地展示设计方案&#xff0c;还能方便后续的工程制图和施工。本文将介绍如何通过3ds Max软件将3D模型导出到CAD软件&#xff0c;并生成高质量的立面图&#xff0c;为您提供实…

英飞凌SiC模块为小米电动车提供动力

至2027年之际&#xff0c;SiC功率模块与裸片产品将荣耀登场&#xff0c;助力小米电动汽车新品SU7璀璨问世。英飞凌&#xff0c;这家业界翘楚&#xff0c;将倾其所能&#xff0c;为小米SU7 Max提供两颗HybridPACK Drive G2 CoolSiC 1200 V模块&#xff0c;如同给电动汽车的心脏注…

遇到好书不容易,《米小圈上学记》与孩子一起见之!幸之!

曾听说&#xff0c;孩子阅读的第一部长篇小说&#xff0c;将会对她的性格和心灵产生长达一生的影响&#xff1b;又听说&#xff0c;在少年养志的阶段&#xff0c;让孩子多读名人传记&#xff0c;一定能有某个人成为她的目标或者偶像。 因此&#xff0c;一直以来我都在寻找最…

亲子失和最大的内耗是:家长总是“说硬话,办软事”!

一声爸妈&#xff0c;一辈子的责任&#xff0c;操不完的心、做不完的事。 然而&#xff0c;爱太满&#xff0c;注定会溢出。爱有边界&#xff0c;我们是父母&#xff0c;更是自己&#xff01; 01 前些时候悠悠起床又开始混账了&#xff01; 气愤的是&#xff0c;周末休息那…

【强化学习】DQN类算法的一些理解

一、DQN算法为什么要使用两个网络&#xff1f; DQN算法通常包含两个网络&#xff1a;一个是评估网络training_network&#xff0c;另一个是目标网络target_network。这两个网络的结构和初始权重是相同的&#xff0c;但它们的权重是不同步更新的。使用两个网络的原因是为了稳定…

计算机的内存是如何实现的

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…