题目描述

众所周知

树链剖分是个好东西QWQ

也是一个代码量破百的算法

基本定义

树路径信息维护算法。
ž将一棵树划分成若干条链,用数据结构去维护每条链,复杂度为O(logN)。
其实本质是一些数据结构/算法在树上的推广
 
华丽的分割线-----------------------------------------------------------------------------------------------------------
 

 
 

具体步骤

预处理
第一遍dfs求出树每个结点的深度deep[x],其为根的子树大小size[x]
以及祖先的信息fa[x][i]表示x往上距离为2^i的祖先
第二遍dfs
ž根节点为起点,向下拓展构建重链
选择最大的一个子树的根继承当前重链
其余节点,都以该节点为起点向下重新拉一条重链
ž给每个结点分配一个位置编号,每条重链就相当于一段区间,用数据结构去维护。
把所有的重链首尾相接,放到同一个数据结构上,然后维护这一个整体即可
修改操作
ž1、单独修改一个点的权值
根据其编号直接在数据结构中修改就行了。
2、修改点u和点v的路径上的权值
(1)若u和v在同一条重链上
直接用数据结构修改pos[u]至pos[v]间的值。
(2)若u和v不在同一条重链上
一边进行修改,一边将u和v往同一条重链上靠,然后就变成了情况(1)。
 
具体代码
 
#include<bits/stdc++.h>
using namespace std;
template <typename T> inline void read(T &x)
{
x=0;int f=1;char c=getchar();
for(;c>'9'||c<'0';c=getchar()) if(c=='-') f=-1;
for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
x*=f;
}
template <typename T> inline void print(T x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) print(x/10);
putchar(x%10+48);
}
int tree[1010001],lazy[1010101];
struct ss{
int v;
int next;
int u;
};
ss s1[1010001];
int head[1101001],cnt;
int w[1010101],wt[1010101];
int n,m,r,mod;
int res=0;
int son[1010101],id[1010101],fa[1010101],tot,deep[1010100],size[1010101],top[1010010];
//--------------------------------------
inline void build(int rt,int l,int r)
{
if(l==r)
{
tree[rt]=wt[l];
tree[rt]%=mod;
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
tree[rt]=(tree[rt<<1]+tree[rt<<1|1])%mod;
}
inline void pushdown(int rt,int len)
{
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
tree[rt<<1]+=lazy[rt]*(len-(len>>1));
tree[rt<<1|1]+=lazy[rt]*(len>>1);
tree[rt<<1]%=mod;
tree[rt<<1|1]%=mod;
lazy[rt]=0;
}
inline void query(int rt,int l,int r,int L,int R)
{
int mid=(l+r)>>1;
if(L<=l&&r<=R)
{
res+=tree[rt],res%=mod;
return;
}
else
{
if(lazy[rt])
pushdown(rt,(r-l+1));
if(L<=mid)
query(rt<<1,l,mid,L,R);
if(R>mid)
query(rt<<1|1,mid+1,r,L,R);
}
}
inline void update(int rt,int l,int r,int L,int R,int k)
{
int mid=(l+r)>>1;
if(L<=l&&r<=R)
lazy[rt]+=k,tree[rt]+=k*(r-l+1);
else
{
if(lazy[rt])
pushdown(rt,r-l+1);
if(L<=mid)
update(rt<<1,l,mid,L,R,k);
if(R>mid)
update(rt<<1|1,mid+1,r,L,R,k);
tree[rt]=(tree[rt<<1]+tree[rt<<1|1])%mod;
}
}
//--------------------------------------
inline void abb(int x,int y)
{
cnt++;
s1[cnt].u=x;
s1[cnt].v=y;
s1[cnt].next=head[x];
head[x]=cnt;
}
inline void DFS(int x,int f,int dep)
{
deep[x]=dep;
fa[x]=f;
size[x]=1;
int MAXX=-1;
for(register int i=head[x];i;i=s1[i].next)
{
int v=s1[i].v;
if(v==f)
continue;
DFS(v,x,dep+1);
size[x]+=size[v];
if(size[v]>MAXX)
son[x]=v,MAXX=size[v];
}
}
inline void DFS_(int x,int TOP)
{
id[x]=++tot;
wt[tot]=w[x];
top[x]=TOP;
if(!son[x])
return;
DFS_(son[x],TOP);
for(register int i=head[x];i;i=s1[i].next)
{
int v=s1[i].v;
if(v==fa[x]||v==son[x])
continue;
DFS_(v,v);
}
}
//--------------------------------------------
inline int qSon(int x)
{
res=0;
query(1,1,n,id[x],id[x]+size[x]-1);
return res;
}
inline void updSon(int x,int k)
{
update(1,1,n,id[x],id[x]+size[x]-1,k);
}
inline void updRange(int x,int y,int k)
{
k%=mod;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])
swap(x,y);
update(1,1,n,id[top[x]],id[x],k);
x=fa[top[x]];
}
if(deep[x]>deep[y])
swap(x,y);
update(1,1,n,id[x],id[y],k);
}
inline int qRange(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])
swap(x,y);
res=0,query(1,1,n,id[top[x]],id[x]),ans+=res,ans%=mod,x=fa[top[x]];
}
if(deep[x]>deep[y])
swap(x,y);
res=0,query(1,1,n,id[x],id[y]),ans+=res;
return ans%mod;
}
int main()
{
read(n),read(m),read(r),read(mod);
for(register int i=1;i<=n;++i)
read(w[i]);
for(register int i=1,a,b;i<n;++i)
read(a),read(b),abb(a,b),abb(b,a);
DFS(r,0,1);
DFS_(r,r);
build(1,1,n);
while(m--)
{
int a,b,c,q;
read(q);
if(q==1)
read(a),read(b),read(c),updRange(a,b,c);
else if(q==2)
read(a),read(b),print(qRange(a,b)),putchar('\n');
else if(q==3)
read(a),read(b),updSon(a,b);
else
read(a),print(qSon(a)),putchar('\n');
}
return 0;
}
 

【模板】树链剖分(Luogu P3384)的更多相关文章

  1. [luogu P3384] [模板]树链剖分

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

  2. luoguP3384 [模板]树链剖分

    luogu P3384 [模板]树链剖分 题目 #include<iostream> #include<cstdlib> #include<cstdio> #inc ...

  3. 树链剖分 - Luogu 3384【模板】树链剖分

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

  4. [洛谷P3384] [模板] 树链剖分

    题目传送门 显然是一道模板题. 然而索引出现了错误,狂wa不止. 感谢神犇Dr_J指正.%%%orz. 建线段树的时候,第44行. 把sum[p]=bv[pos[l]]%mod;打成了sum[p]=b ...

  5. P3384 [模板] 树链剖分

    #include <bits/stdc++.h> using namespace std; typedef long long ll; int n, m, rt, mod, cnt, to ...

  6. 模板 树链剖分BFS版本

    //点和线段树都从1开始 //边使用vector vector<int> G[maxn]; ],num[maxn],iii[maxn],b[maxn],a[maxn],top[maxn], ...

  7. 『题解』洛谷P3384 【模板】树链剖分

    Problem Portal Portal1: Luogu Description 如题,已知一棵包含\(N\)个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作\(1\): ...

  8. 树链剖分详解(洛谷模板 P3384)

    洛谷·[模板]树链剖分 写在前面 首先,在学树链剖分之前最好先把 LCA.树形DP.DFS序 这三个知识点学了 emm还有必备的 链式前向星.线段树 也要先学了. 如果这三个知识点没掌握好的话,树链剖 ...

  9. Luogu P3384 【【模板】树链剖分】

    转载请注明出处,部分内容引自banananana大神的博客 ~~别说你不知道什么是树~~╮(─▽─)╭(帮你百度一下) 先来回顾两个问题:1,将树从x到y结点最短路径上所有节点的值都加上z 这也是个模 ...

随机推荐

  1. 最全面阐述WebDataBinder理解Spring的数据绑定

    每篇一句 不要总问低级的问题,这样的人要么懒,不愿意上网搜索,要么笨,一点独立思考的能力都没有 相关阅读 [小家Spring]聊聊Spring中的数据绑定 --- DataBinder本尊(源码分析) ...

  2. JavaScript函数及闭包

    前面一片文章讲到过一点函数,了解到每声明一个函数就会产生一个作用域.而外面的作用域访问不了里面的作用域(把里面的变量和函数隐藏起来),而里面的可以访问到外面的.对于隐藏变量和函数是一个非常有用的技术. ...

  3. Excel催化剂开源第51波-Excel催化剂遍历单元格操作性能保障

    在Excel催化剂推出的这一年多时间里,经常性听到一种声音,大概意思是真正会写代码的人,都不会看上Excel催化剂写出来的功能,自己造一个更舒服贴心,仿佛会一点VBA就可以天下无敌一般,也好像Exce ...

  4. 爬虫的盗亦有道Robots协议

    爬虫的规定 Robots协议 网站开发者对于网络爬虫的规范的公告,你可以不遵守可能存在法律风险,但尽量去遵守 Robots协议:在网页的根目录+robots.txt Robots协议的基本语法: #注 ...

  5. c语言进阶11-算法设计思想

    一.  算法设计的要求: 为什么要学算法? /* 输出Hello word! */ #include "stdio.h" void main() { printf("He ...

  6. 调用百度API进行文本纠错

    毕设做的是文本纠错方面,然后今天进组见研究生导师 .老师对我做的东西蛮感兴趣.然后介绍自己现在做的一些项目,其中有个模块需要有用到文本纠错功能. 要求1:有多人同时在线编辑文档,然后文档功能有类似Wo ...

  7. python课堂整理4---列表的魔法

    一.list   类, 列表 li = [1, 12, 9, "age", ["大白", "小黑"], "alex"] ...

  8. mount命令中offset参数的意义

    mount命令中offset参数的意义        感觉好久没有来写东西了,最近一直忙个不停,今天也一样,总感觉时间不够用,唉,这里来临时总结一下工作中的一点小收获吧.今天要说的是我们常用的解压IM ...

  9. 转 java - java反射机制创建对象

    转 https://blog.csdn.net/nch_ren/article/details/78814080 1.创建service实现类 package com.springstudy.refl ...

  10. cookbook_类与对象

    1修改实例的字符串表示 可以通过定义__str__()和__repr__()方法来实现 class Pair: def __init__(self,x,y): self.x = x self.y = ...