P3384 【模板】轻重链剖分

首先先说一下基本概念:
1.重儿子:一个结点的所有儿子中,大小最大的那个(最重的,所以说只有一个,如果有多个儿子的大小相等那就随便取一个)。
2.轻儿子:一个结点的儿子除了重儿子以外的所有儿子都是轻儿子。(根节点为轻儿子)
3.重链:从一个轻儿子开始,一路往重儿子走,连出来的链叫重链。
4.轻链:除了重链全是轻链。

如下图:
重链即为标染色点连出的边。
dfs序即为即为图中红色标号。

那么我们如何处理出这个dfs序呢?
通过两个dfs.

第一个dfs需要:
1.标记结点的父亲
2.标记结点的重儿子
3.标记结点的深度
4.结点的大小
第二个dfs需要:
为什么要第二遍才可以(因为需要第一遍跑出来的重儿子)
1.标记重链的开始结点。
2.结点权值的dfs序与时间戳。

如下图有两条重链:
第一条重链为FHKL 他们的开始结点都为F
第二条重链为CD 他们的开始结点都为C
这个标记有什么用处,到后面就明白了。

我们再来看这个例题:

P3384 【模板】轻重链剖分

对于操作一和操作二,我们可以知道,树上点与点之间的路径是唯一的(不重复走的情况下)。
所以我们可以得知:

引理:除根节点外的任何一个结点的父亲结点都一定在一条重链上。
证明:因为父亲结点存在儿子,所以一定存在重儿子,所以一定在一条重链上。

所以:
对于x-y之间的路径:是由重链的一部分和叶子节点组成的。
那么我们对于不同的路径情况分类讨论一下即可。
1.假设x、y在一条重链上,那么情况就变得简单了(因为重链上的序号是连续的)。
我们直接把x和y对应的dfs序拿出来在线段树上操作一下即可。
那么问题是如何判断x、y是否在一条重链上呢?
标记重链的开始结点。 这一个操作用上了,只要查询他们两个值的开始结点相同,那么即为同一重链。
2.如果不在一条重链上呢?
那么我们可以维护两个指针分别指向两个结点。
不停的让所在链的顶部结点深度较深那个指针沿着重链往上跳(直接跳到重链开始结点),顺便在线段树上维护操作(因为重链上的结点是连续的)。
到达顶部结点后,我们让他跳到顶部结点的父亲结点。然后继续循环如上操作,直到两指针相遇(或者到了同一条重链上)。

代码:

/*Keep on going Never give up*/
//#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define endl '\n'
//#define int long long
using namespace std;
const int maxn=1e6+10;
int mod=998244353;struct node{int to,next;
}edge[maxn];int tot,head[maxn];void init(){memset(head,-1,sizeof head);
}void adde(int u,int v){edge[tot].to=v,edge[tot].next=head[u];head[u]=tot++;edge[tot].to=u,edge[tot].next=head[v];head[v]=tot++;
}
int v[maxn];
int fa[maxn],dep[maxn],siz[maxn],son[maxn];void dfs1(int u,int f){fa[u]=f;  //标记父亲dep[u]=dep[f]+1;  //标记深度siz[u]=1; //初始化大小for(int i=head[u];~i;i=edge[i].next){int v=edge[i].to;if(v==f) continue;dfs1(v,u);siz[u]+=siz[v];  //累加大小if(siz[v]>siz[son[u]]){  //找重儿子son[u]=v;}}
}
int cnt,dfn[maxn],top[maxn],w[maxn];
void dfs2(int u,int t){dfn[u]=++cnt;top[u]=t;w[cnt]=v[u];  //重新把结点的值转移到连续序列上if(!son[u]) return ;dfs2(son[u],t);  //有限递归重儿子for(int i=head[u];~i;i=edge[i].next){int v=edge[i].to;if(v==fa[u]||v==son[u]) continue ;dfs2(v,v);  //头节点为当前结点开始递归}
}
int tree[maxn],lazy[maxn];
void push_down(int node,int l,int r){lazy[node*2]+=lazy[node];lazy[node*2+1]+=lazy[node];int mid=(l+r)/2;tree[node*2]+=(mid-l+1)*lazy[node]%mod;tree[node*2+1]+=(r-mid)*lazy[node]%mod;lazy[node]=0;
}
void build(int node,int start,int ends){if(start==ends){tree[node]=w[start]%mod;return ;}int mid=(start+ends)/2;build(node*2,start,mid);build(node*2+1,mid+1,ends);tree[node]=(tree[node*2]+tree[node*2+1])%mod;
}void update(int node,int start,int ends,int l,int r,int val){if(start>=l&&ends<=r){lazy[node]+=val;tree[node]+=(ends-start+1)*val%mod;return ;}if(lazy[node]) push_down(node,start,ends);int mid=(start+ends)/2;if(l<=mid) update(node*2,start,mid,l,r,val);if(mid<r) update(node*2+1,mid+1,ends,l,r,val);tree[node]=(tree[node*2]+tree[node*2+1])%mod;
}int query(int node,int start,int ends,int l,int r){if(start>=l&&ends<=r){return tree[node]%mod;}if(lazy[node]) push_down(node,start,ends);int mid=(start+ends)/2;int res=0;if(l<=mid) res+=query(node*2,start,mid,l,r);if(mid<r) res+=query(node*2+1,mid+1,ends,l,r);return res%mod;
}
int n,m,r;
void mchain(int x,int y,int z){z%=mod;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);update(1,1,n,dfn[top[x]],dfn[x],z);x=fa[top[x]];}if(dep[x]>dep[y]) swap(x,y);update(1,1,n,dfn[x],dfn[y],z);
}int qchain(int x,int y){int ret=0;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);ret+=query(1,1,n,dfn[top[x]],dfn[x]);x=fa[top[x]];}if(dep[x]>dep[y]) swap(x,y);ret+=query(1,1,n,dfn[x],dfn[y]);return ret%mod;
}
signed main(){ios::sync_with_stdio(false);cin.tie(nullptr);init();cin>>n>>m>>r>>mod;for(int i=1;i<=n;i++) cin>>v[i];for(int i=0;i<n-1;i++){int x,y;cin>>x>>y;adde(x,y);}dfs1(r,r);dfs2(r,r);build(1,1,n);for(int i=0;i<m;i++){int opt;cin>>opt;if(opt==1){int x,y,z;cin>>x>>y>>z;mchain(x,y,z);}else if(opt==2){int x,y;cin>>x>>y;cout<<qchain(x,y)<<endl;}else if(opt==3){int x,y;cin>>x>>y;update(1,1,n,dfn[x],dfn[x]+siz[x]-1,y);}else{int x;cin>>x;cout<<query(1,1,n,dfn[x],dfn[x]+siz[x]-1)<<endl;}}
}

树链剖分(轻重链剖分) 讲解 (模板题目 P3384 【模板】轻重链剖分 )相关推荐

  1. 树链剖分 讲解+模板+习题

    今天我们来讲一下树链剖分 树链剖分是什么? 树链剖分是一种用来维护树上路径信息的在线方法,可以处理在线. 通常通过一种方法,将一棵树剖分成若干条链,然后通过数据结构(线段树,BIT等)去维护. 我们通 ...

  2. 树链剖分(轻重链)入门

    写在前面 仅想学树剖LCA的同学其实不必要了解线段树 前置知识:树形结构,链式前向星(熟练),线段树(熟练),DFS序(熟练),LCA(了解定义) 树链剖分(树剖):将树分解为一条条不相交的,从祖先到 ...

  3. 树链剖分——轻重链剖分

    2022年01月27日,第十三天 1. 题目链接:P3384 [模板]轻重链剖分/树链剖分 思路:树链剖分直接搞,时间复杂度为 O(nlog2n)O(nlog^2n)O(nlog2n) ,通过模板题, ...

  4. 树链剖分(轻重链剖分)

    树链剖分,是一种将树剖分为链,在链上进行各种操作以达到目的的算法.树链剖分(轻重链剖分)可以解决lca(最近公共祖先),树上操作(对树上两点及经过的路的权值进行求和,修改等操作)等一类操作.对于这些问 ...

  5. 树链剖分(轻重链剖+长链剖)

    Part 0 一堆废话 本来树链剖分我是不打算写帖子的,因为我一道树剖的题都没做. 后面在刷树上启发式合并的题目时刚好遇到某道到现在都没调出来的题目要码树剖,感觉这道题在敲烂警钟提醒我好好学树剖,所以 ...

  6. 树链剖分之重链剖分详解

    树链剖分之重链剖分详解 一些概念 算法讲解 应用 求最近公共祖先 对树上的一条链进行修改和查询 相关练习题 一些概念 在学习重链剖分前,首先要明白以下几个概念: 中二重儿子:就是一个节点的儿子中最&q ...

  7. 【模板】树链剖分 P3384

    题目链接 //部分转自:https://www.luogu.org/problemnew/solution/P3384 初学树链剖分,感觉这个模板题还是容易理解的,但是实在是码量很大的. 知识点: 重 ...

  8. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释...

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

  9. 树链剖分概念及模板 + 例题 [POJ3237 tree + 软件包管理器]

    文章目录 概念 模板 例题1:软件包管理器 题目 题解 代码实现 例题2:POJ3237 tree 题目 题解 代码实现 概念 树链剖分主要是用于解决以下这两个问题. 1.更改树上点x到点y的最短路径 ...

最新文章

  1. python 无头模式 绕过检测_Python chrome 无头模式的问题
  2. Redis命令——Keys相关
  3. SpringMVC请求处理流程
  4. 贪吃蛇的编程python_python实现贪吃蛇游戏
  5. 【编撰】Directfb 深入 002 DirectFB内存分配与管理:surface pool
  6. java 模块开发_java模块化开发
  7. 阿里DRUID数据源
  8. 帝国备份王(Empirebak) \class\functions.php、\class\combakfun.php GETSHELL vul
  9. Docker 教程、架构、Linux下的安装
  10. WPF中嵌套charts图表查询数据
  11. Win10应用商店无法连接解决方案
  12. 数学建模算法与应用习题1-3 解析 MATLAB 整数规划
  13. html中的分页条怎么写,html如何制作分页
  14. java连接hsql数据库_hsql数据库使用详解(入门)及快速使用
  15. AHCI驱动中的cmd
  16. “百度百科六度分隔理论”(简单版)
  17. ZZULIOJ:1035: 分段函数求值
  18. Springboot开关柜综合监测信息查询系统毕业设计-附源码191550
  19. 学习python第八节课:可变与不可变对象
  20. 苹果Mac 上照片调整工具的使用方法

热门文章

  1. JSP大作业数据库_本地MySQL【种种问题】
  2. 在报文摘要算法MD5中,首先要进行明文分组与填充,其中分组时明文报文摘要按照(42)位分组。【答案】C
  3. 【SLAM】卡尔曼滤波:究竟滤了谁?
  4. 干货|简单理解梯度下降及线性回归
  5. 问题 A: 第二题(划分一个集合为差值最小的两个子集合)
  6. 接口测试用例测试模板
  7. 46、我的C#学习笔记12
  8. Level3公司在哥伦比亚开通运营第三个数据中心
  9. 设计模式入门之原型模式Prototype
  10. 【JavsScript】推荐五款流行的JavaScript模板引擎