树链剖分代码细解

news/2024/11/13 14:25:49

总结回顾类文章,酌情观看。


Shape Of You
头图

Linux找图太难了呜呜
image

The club isn't the best place to find a lover
So the bar is where I go
Me and my friends at the table doing shots
Drinking faster and then we talk slow
You come over and start up a conversation with just me
And trust me I'll give it a chance now
Take my hand, stop, Put Van The Man on the jukebox
And then we start to dance, and now I'm singing like
Girl, you know I want your love
Your love was handmade for somebody like me
Come on now, follow my lead
I may be crazy, don't mind me, say
Boy, let's not talk too much
Grab on my waist and put that body on me
Come on now, follow my lead
Come—come on now, follow my lead
I'm in love with the shape of you
We push and pull like a magnet do
Although my heart is falling too
I'm in love with your body
And last night you were in my room
And now my bedsheets smell like you
Every day discovering something brand new
I'm in love with your body

一些

HAOI2015 树上操作 代码拆分

	void Wadd(int u,int v){to[++cnt]=v;ne[cnt]=hh[u];hh[u]=cnt;}

标准的链式前向星连边。

    void Wpushup(int rt){tsum[rt]=tsum[ls]+tsum[rs];}

推上(更新)操作,进行一些更改后会随之变动的数据,如和与最大值。

    void Wpushdown(int rt,int lenn){tsum[ls]+=laz[rt]*(lenn-(lenn>>1));tsum[rs]+=laz[rt]*(lenn>>1);laz[ls]+=laz[rt],laz[rs]+=laz[rt];laz[rt]=0;}

推下(下放)操作,进行一些需要先处理的更改,主要为 \(lazy\) 标记的下放。

    void Wbuild(int rt,int l,int r){if(l==r){tsum[rt]=wt[l];return;}Wbuild(ls,l,mid);Wbuild(rs,mid+1,r);Wpushup(rt);}

建树。

    void Wadp(int rt,int l,int r,int x,ll v){if(l==r){tsum[rt]+=v;return;}if(laz[rt])Wpushdown(rt,r-l+1);if(x<=mid)Wadp(ls,l,mid,x,v);elseWadp(rs,mid+1,r,x,v);Wpushup(rt);}

单点更改。\(l\)\(r\) 为当前节点的左右边界,\(x\) 为修改的点编号,\(v\) 为更改后 / 增减的值。有 \(lazy\) 标记先下放,下放后随之更新。(不更新会WA)

    void Wadi(int rt,int l,int r,int x,int y,ll v){if(x<=l&&r<=y){laz[rt]+=v;tsum[rt]+=v*(r-l+1);return ;}if(laz[rt])Wpushdown(rt,r-l+1);if(x<=mid)Wadi(ls,l,mid,x,y,v);if(y>mid)Wadi(rs,mid+1,r,x,y,v);Wpushup(rt);}

整条链修改(区间修改)。\(x\)\(y\)分别为修改的左右边界,操作基本同上,加值时用 \(lazy\) 标记。

    ll Wqsum(int rt,int l,int r,int x,int y){if(x<=l&&r<=y)return tsum[rt];if(laz[rt])Wpushdown(rt,r-l+1);ll ans=0;if(x<=mid)ans+=Wqsum(ls,l,mid,x,y);if(y>mid)ans+=Wqsum(rs,mid+1,r,x,y);return ans;}

区间查询和。可以自己画个草图模拟一下,只要左右区间中有在所求范围内的就递归下去。

关于为什么这里pushdown后不用pushup

我个人的想法是:做修改操作时,已经将当前的 \(sum\) 更新过了,即使 \(lazy\) 没有下放,导致的结果只会是当前 \(sum\) 仍是正确的,但子区间答案是未更新的,所以不会影响结果正确性。

有不同想法也可以评论留言。

    ll Wquesum(int x,int y){ll ans=0;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);ans+=Wqsum(1,1,n,id[top[x]],id[x]);x=fa[top[x]];}if(dep[x]<dep[y])swap(x,y);ans+=Wqsum(1,1,n,id[y],id[x]);return ans;}

求两个节点最短路径上权值和。利用已经求出的 LCA 相关信息不断向上取当前两点较深的那个至链首的区间和,然后跳到链首的父节点,重复上述操作,直到两点在同一条链上,一个区间和收尾。

    void Wdfs1(int u,int f,int deep){dep[u]=deep,fa[u]=f,siz[u]=1;for(int i=hh[u];i!=-1;i=ne[i]){int v=to[i];if(v==f)continue;Wdfs1(v,u,deep+1);siz[u]+=siz[v];if(siz[v]>siz[son[u]])son[u]=v;}}

dfs1 函数,负责求出点的深度,父节点,子树大小,以及重子节点编号,递归形式还是比较好理解的。

    void Wdfs2(int u,int topf){id[u]=++tot,top[u]=topf;wt[tot]=w[u];if(!son[u])return;Wdfs2(son[u],topf);for(int i=hh[u];i!=-1;i=ne[i]){int v=to[i];if(v==fa[u]||v==son[u])continue;Wdfs2(v,v);}}

dfs2 函数,负责求出每一个点的新的编号,新编号下的权值,以及所在链的链首。先遍历重子节点,在遍历轻子节点,轻子节点所在一条新的链,自己为链首。

    short main(){memset(hh,-1,sizeof hh);n=qr,m=qr;fo(i,1,n)w[i]=qr;fo(i,1,n-1){int a=qr,b=qr;Wadd(a,b),Wadd(b,a);}Wdfs1(1,0,1),Wdfs2(1,1);Wbuild(1,1,n);while(m--){int op=qr,x=qr;if(op==1){int y=qr;Wadp(1,1,n,id[x],y);}else if(op==2){int y=qr;Wadi(1,1,n,id[x],id[x]+siz[x]-1,y);}elseprintf("%lld\n",Wquesum(1,x));}return Ratio;}

主函数。\(head\) 数组初始化,输入,连边。两次 dfs 初始化,建树,然后进行所需的操作。


完结撒花~

image

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

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

相关文章

系统国际化之多语言解决方案| 京东物流技术团队

1. 背景随着京东各业务板块国际化进程的不断推进,诸多业务已经融入了多元文化中,一个一体化的多语言系统解决方案成为各个技术团队讨论的焦点。国际物流系统凭借在国际化领域多年的经验,特别是在系统多语言处理上长期的经验积累,总结了一套标准的系统多语言框架,旨在为大家…

MDS800-16-ASEMI整流模块MDS800-16

MDS800-16-ASEMI整流模块MDS800-16编辑:ll MDS800-16-ASEMI整流模块MDS800-16 型号:MDS800-16 品牌:ASEMI 封装:MDS 平均正向整流电流(Id):800A 最大反向击穿电压(VRM):1600V 产品引线数量:5 产品内部芯片个数:6 产品内部芯片尺寸:102MIL 峰值正向漏电流:<10u…

低功耗、高性价比的XCKU3P-1FFVA676E、XCKU3P-L1FFVB676I、XCKU3P-L2FFVB676E现场可编程门阵列产品概述

Kintex UltraScale+ 器件在 FinFET 节点中提供高性价比,为需要高端功能(包括 33Gb/s 收发器和 100G 连接内核)的应用提供了经济高效的解决方案。Kintex UltraScale+ 器件在 FinFET 节点中提供高性价比,为需要高端功能(包括 33Gb/s 收发器和 100G 连接内核)的应用提供了经…

CaffeineCache Api介绍以及与Guava Cache性能对比| 京东物流技术团队

一、简单介绍: CaffeineCache和Guava的Cache是应用广泛的本地缓存。 在开发中,为了达到降低依赖、提高访问速度的目的。会使用它存储一些维表接口的返回值和数据库查询结果,在有些场景下也会在分布式缓存上再加上一层本地缓存,用来减少对远程服务和数据库的请求次数。 Caff…

nps内网穿透使用

原版的https://github.com/ehang-io/nps已经停止更新 新版的地址 https://github.com/yisier/nps 一、安装 可以下载已经编译好的程序安装。网上有很多教程。 也可以下载源码编译,需要注意的是如果到cmd/nps下面编译,运行的时候,需要把conf目录拷贝到nps目录下才能运行,缺少…

(二)Redis 数据类型与结构

Redis 数据类型与结构1、值的数据类型 Redis “快”取决于两方面,一方面,它是内存数据库,另一方面,则是高效的数据结构。Redis 键值对中值的数据类型,也就是数据的保存形式有5种:String(字符串)、List(列表)、Hash(哈希)、Set(集合)和 Sorted Set(有序集合)。这…

高薪线下周末班马上开班,手把手带你提升职业技能

管理学大师彼得德鲁克说“终身学习是现在社会的生存法则”,而现实中,很少有人能清醒地意识到这一点,人们总是习惯在舒适区兜圈,重复做已经掌握的事情,对真正需要突破的职业困境视而不见。 偶尔看到同事跳槽涨薪,技术越来越娴熟,自己也期望着可以跟他们一样,幻想着有一天…

dapr离线初始化

打开地址: https://github.com/dapr/installer-bundle/releases 下载 daprbundle_windows_amd64.zip 解压以后,放到此目录下,注意放的是daprbundle文件夹下内容 D:\daprbundle_v1.13.2指定目录进行初始化: dapr init --from-dir D:\daprbundle_v1.13.2 最后初始化完成,如下图…