洛谷P3384

#include <bits/stdc++.h>
#define DBG(x) cerr << #x << " = " << x << endl;
const int maxn = 1e5+5;
using namespace std; inline int read(){
int x=0,f=1;char ch=getchar();
while(ch < '0' || ch > '9'){if(ch=='-')f=-1;ch=getchar();}
while(ch >= '0' && ch <= '9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
} int n,m,rot,mod;
int w[maxn],wt[maxn];///剖分前后的点权,不要抄错QAQ
int head[maxn],tot;
int cnt,dep[maxn],siz[maxn],fa[maxn],son[maxn],id[maxn],top[maxn];///son[i]表示i的重儿子,top[i]表示i所在链的顶点
int ans; struct treenode{
int l,r,val,add;
}tree[maxn<<2]; struct edgenode{
int to,next;
}edge[maxn<<1]; void addedge(int u,int v){
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
} void push_up(int x){
tree[x].val=tree[x<<1].val+tree[x<<1|1].val;
tree[x].val%=mod;
} void push_down(int x,int len){
if(tree[x].add){
tree[x<<1].add+=tree[x].add;
tree[x<<1|1].add+=tree[x].add;
tree[x<<1].val+=(len-(len>>1))*tree[x].add;
tree[x<<1|1].val+=(len>>1)*tree[x].add;
tree[x<<1].val%=mod;
tree[x<<1|1].val%=mod;
tree[x].add=0;
}
} void build(int i,int l,int r){
tree[i].l=l;
tree[i].r=r;
tree[i].add=0;
if(l == r){
tree[i].val=wt[l];
tree[i].val%=mod;
return;
}
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
push_up(i);
} void update(int i,int l,int r,int L,int R,int c){
if(l >= L && r <= R){
tree[i].val+=(r-l+1)*c;
tree[i].add+=c;
return;
}
push_down(i,r-l+1);
int mid=(l+r)>>1;
if(L <= mid)update(i<<1,l,mid,L,R,c);
if(R > mid)update(i<<1|1,mid+1,r,L,R,c);
push_up(i);
} void query(int i,int l,int r,int L,int R){
if(l >= L && r <= R){
ans+=tree[i].val;
ans%=mod;
return;
}
push_down(i,r-l+1);
int mid=(l+r)>>1;
if(L <= mid)query(i<<1,l,mid,L,R);
if(R > mid)query(i<<1|1,mid+1,r,L,R);
} void dfs1(int x,int pre,int deep){///确定各节点层次,子树大小,父节点编号,重儿子编号
dep[x]=deep;
fa[x]=pre;
siz[x]=1;
int maxson=-1;
for(int i=head[x];i != -1;i=edge[i].next){
int v=edge[i].to;
if(v != pre){
dfs1(v,x,deep+1);
siz[x]+=siz[v];
if(siz[v] > maxson){maxson=siz[v];son[x]=v;}
}
}
} void dfs2(int x,int topf){///确定各链的信息,包括链的顶点以及链上点的新编号
id[x]=++cnt;
wt[id[x]]=w[x];
top[x]=topf;
if(!son[x])return;
dfs2(son[x],topf);
for(int i=head[x];i != -1;i=edge[i].next){
int v=edge[i].to;
if(v == fa[x] || v == son[x])continue;
dfs2(v,v);
}
} void spilt(){
dfs1(rot,0,1);
dfs2(rot,rot);
build(1,1,n);
}
/*查询两点路径上的点权和*/
int qRange(int x,int y){///让深度深的点往上跳到顶点并更新对答案的贡献
int res=0; ///之后更新到旧链顶上的链,重复过程直到两点在同一条链上
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]])swap(x,y);
ans=0;
query(1,1,n,id[top[x]],id[x]);
res+=ans;
res%=mod;
x=fa[top[x]];
}
if(dep[x] > dep[y])swap(x,y);
ans=0;
query(1,1,n,id[x],id[y]);
res+=ans;
return res%mod;
}
/*更新同查询*/
void updRange(int x,int y,int c){
c%=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],c);
x=fa[top[x]];
}
if(dep[x] > dep[y])swap(x,y);
update(1,1,n,id[x],id[y],c);
}
/*查询子树点权和*/
int qSon(int x){///由于新编号连续,直接查询树根到树根+树的大小,这段区间对应整个子树
ans=0;
query(1,1,n,id[x],id[x]+siz[x]-1);
return ans;
}
/*更新同查询*/
void updSon(int x,int c){
update(1,1,n,id[x],id[x]+siz[x]-1,c);
} int main(){
memset(head,-1,sizeof head);
n=read(),m=read(),rot=read(),mod=read();
for(int i=1;i<=n;i++)w[i]=read();
for(int i=1;i<=n-1;i++){
int a=read(),b=read();
addedge(a,b);
addedge(b,a);
}
spilt();///剖分
for(int i=1;i<=m;i++){
int op,x,y,z;
op=read();
if(op == 1){
x=read(),y=read(),z=read();
updRange(x,y,z);
}
if(op == 2){
x=read(),y=read();
printf("%d\n",qRange(x,y));
}
if(op == 3){
x=read(),y=read();
updSon(x,y);
}
if(op == 4){
x=read();
printf("%d\n",qSon(x));
}
}
return 0;
}

  

树链剖分模板(洛谷P3384)的更多相关文章

  1. 【树链剖分】洛谷P3384树剖模板

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

  2. 树链剖分( 洛谷P3384 )

    我们有时候遇到这样一类题目,让我们维护树上路径的某些信息,这个时候发现我们无法用线段树或者树状数组来维护这些信息,那么我们就有着一种新的数据结构,树剖:将一棵树划分成若干条链,用数据结构去维护每条链, ...

  3. 【树链剖分】洛谷P3379 树链剖分求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  4. 树链剖分【洛谷P4114】 Qtree1

    P4114 Qtree1 题目描述 给定一棵n个节点的树,有两个操作: CHANGE i ti 把第i条边的边权变成ti QUERY a b 输出从a到b的路径中最大的边权,当a=b的时候,输出0 码 ...

  5. 树链剖分【洛谷P2590】 [ZJOI2008]树的统计

    P2590 [ZJOI2008]树的统计 题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w. 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把 ...

  6. 树链剖分【洛谷P1505】 [国家集训队]旅游

    P1505 [国家集训队]旅游 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城 ...

  7. 树链剖分【洛谷P3833】 [SHOI2012]魔法树

    P3833 [SHOI2012]魔法树 题目描述 Harry Potter 新学了一种魔法:可以让改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的新法术. 这棵果树共有N个节点,其中节 ...

  8. BZOJ 2243 染色 | 树链剖分模板题进阶版

    BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

  9. 算法复习——树链剖分模板(bzoj1036)

    题目: 题目背景 ZJOI2008 DAY1 T4 题目描述 一棵树上有 n 个节点,编号分别为 1 到 n ,每个节点都有一个权值 w .我们将以下面的形式来要求你对这棵树完成一些操作:I.CHAN ...

随机推荐

  1. C# Winform 对话框控件&简单记事本

    一.对话框 1.弹出可供用户选择“确定”.“取消”的对话框 Dialogresult dr =  MessigeBox.Show("这里显示的是对话框的内容","这里显示 ...

  2. poj2259 Team Queue

    吼哇,又是水题. 我本来准备开1010个queue的,但是STL容器里好像只有vector滋磁开组,于是只好数组模拟... 然后模拟过了...... #include <cstdio> # ...

  3. Remote debugger is in a background tab which may cause apps to perform slowly. Fix this by foregrounding the tab (or opening it in a separate window).

    先上代码: /** * Sample React Native App * https://github.com/facebook/react-native * * @format * @flow * ...

  4. PHP快速排序算法

    说明: 通过设置一个初始中间值,来将需要排序的数组分成3部分,小于中间值的左边,中间值,大于中间值的右边,继续递归用相同的方式来排序左边和右边,最后合并数组 示例: <?php $a = arr ...

  5. echarts map地图设置外边框或者阴影

    geo: { map: 'china', center: [112.194115019531, 23.582111640625], zoom: 12, aspectScale: 1, //长宽比 la ...

  6. Circular view path xxx would dispatch back to the current handler URL,Check your ViewResolver setup

    Circular view path xxx would dispatch back to the current handler URL 通过原因分析,造成问题有两个因素:1). 缺省转发, 2). ...

  7. halcon几何变换(仿射变换)

    旋转.平移.镜像.缩放.斜切,可参考https://blog.csdn.net/machaoyu86/article/details/51182473 仿射变换前,需要获得仿射变换矩阵. 关于shap ...

  8. windows怎样查看被程序占用的端口

    1. netstat -ano  显示所有端口与任务管理器中的pid对应,通过pid打开任务管理器查询占用进程 附录:在命令行中输入netstat /? 可以查看netstat的相关信息.C:\Doc ...

  9. node.js(小案例)_实现学生信息增删改

    一.前言 本节内容主要对小案例做一个总结: 1.如何开始搭建小项目 2.路由设计 3.模块应用 4.项目源码以及实现过程github地址: 项目演示如下: 二.主要内容 1.项目的关键性js源码: 项 ...

  10. PHP下安装memcached

    tar xvf libevent-2.0.21-stable.tar.gzcd libevent./configure -prefix=/usr/local/libeventmake &&am ...