洛谷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. java 8: ClassNotFoundException: sun.jdbc.odbc.JdbcOdbcDriver

    转眼之间, java 11都快要推出了. 而我一直都在 java 7环境下写代码,真的不想升级,不想改变什么,可世界每天都在变化. 最近因为服务端需要SNI,而 java 7 只支持客户端的SNI,只 ...

  2. mciSendString 多线程播放多首音乐 & 注意事项

    昨天晚上遇到一个问题: 使用 mciSendString  控制播放多首音乐的时候,出现最后一次播放的音乐无法通过 mciSendString ("close mp3") 关闭音乐 ...

  3. Codeforces Round #523 (Div. 2) D. TV Shows

    传送门 https://www.cnblogs.com/violet-acmer/p/10005351.html 题意: 有n个节目,每个节目都有个开始时间和结束时间. 定义x,y分别为租电视需要的花 ...

  4. vue-cli+webpack在生成的项目中使用bootstrap的方法

    在一个html页面中加入bootstrap是很方便,就是一般的将css和js文件通过Link和Script标签就行.那么在一个用vue-vli生成的前端项目中如何加入?因为框架不一样了,略微要适应一下 ...

  5. 3D游戏的角色移动

    * -----英雄的移动控制 * * * * */ using System.Collections; using System.Collections.Generic; using UnityEng ...

  6. 基于TC做流量控制

    1 模拟延迟传输简介 netem 与 tc: netem 是 Linux 2.6 及以上内核版本提供的一个网络模拟功能模块.该功能模块可以用来在性能良好的局域网中,模拟出复杂的互联网传输性能,诸如低带 ...

  7. storm集群配置

    环境:centos6.4软件:jzmq-master-----java与c++通讯的桥梁,有了它,就可以使用zeromp了storm-0.8.2zeromq-2.1.7-----号称史上最牛逼的消息队 ...

  8. django中文学习资料

    Django 2.0 中文官方文档地址: https://docs.djangoproject.com/zh-hans/2.0/ <Django Girls>中文版地址: https:// ...

  9. 虚拟机centos无法连接外网时怎么处理

    1. 首先查看service 如果没有启动请启动这2个服务. 2. 在虚拟机那重启网络端口 ifdown ens33 ifup ens33

  10. 《玩转Django2.0》读书笔记-探究视图

    <玩转Django2.0>读书笔记-探究视图 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 视图(View)是Django的MTV架构模式的V部分,主要负责处理用户请求 ...