chuansongmen

题目描述

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

操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z

操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和

操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z

操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和

输入输出格式

输入格式:

第一行包含4个正整数N、M、R、P,分别表示树的结点个数、操作个数、根节点序号和取模数(即所有的输出结果均对此取模)。

接下来一行包含N个非负整数,分别依次表示各个节点上初始的数值。

接下来N-1行每行包含两个整数x、y,表示点x和点y之间连有一条边(保证无环且连通)

接下来M行每行包含若干个正整数,每行表示一个操作,格式如下:

操作1: 1 x y z

操作2: 2 x y

操作3: 3 x z

操作4: 4 x

输出格式:

输出包含若干行,分别依次表示每个操作2或操作4所得的结果(对P取模)

输入输出样例

输入样例#1:

5 5 2 24
7 3 7 8 0
1 2
1 5
3 1
4 1
3 4 2
3 2 2
4 5
1 5 1 3
2 1 3

输出样例#1:

2
21

说明

时空限制:1s,128M

数据规模:

对于30%的数据: N \leq 10, M \leq 10N≤10,M≤10

对于70%的数据: N \leq {10}^3, M \leq {10}^3N≤10​3​​,M≤10​3​​

对于100%的数据: N \leq {10}^5, M \leq {10}^5N≤10​5​​,M≤10​5​​

( 其实,纯随机生成的树LCA+暴力是能过的,可是,你觉得可能是纯随机的么233 )

样例说明:

树的结构如下:

各个操作如下:

故输出应依次为2、21(重要的事情说三遍:记得取模)

code

#include<cstdio>
#include<iostream>
using namespace std;
const int maxn=500005;
typedef long long LL;
int n,m,u,v,t,r,sumedge,temp;
LL mod;
int head[maxn],son[maxn],dad[maxn],top[maxn],heavy_son[maxn];
int id[maxn],real[maxn],depth[maxn],a[maxn];
struct Edge{int x,y,nxt;Edge(int x=0,int y=0,int nxt=0):x(x),y(y),nxt(nxt){}
}edge[maxn];
struct segment_tree{LL l,r,sum,tag;
}tr[maxn];
void add(int x,int y){edge[++sumedge]=Edge(x,y,head[x]);head[x]=sumedge;
}
void dfs1(int k,int fa){dad[k]=fa;depth[k]=depth[fa]+1;son[k]=1;for(int i=head[k];i;i=edge[i].nxt){int v=edge[i].y;if(v!=fa){dfs1(v,k);son[k]+=son[v];if(!heavy_son[k]||son[heavy_son[k]]<son[v])heavy_son[k]=v;}}
}
void dfs2(int k,int fir){top[k]=fir;id[k]=++temp;real[temp]=k;if(!heavy_son[k])return;dfs2(heavy_son[k],fir);for(int i=head[k];i;i=edge[i].nxt){int v=edge[i].y;if(v!=dad[k]&&v!=heavy_son[k])dfs2(v,v);}
}
void pushup(int rt){tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
}
void pushdown(int rt){tr[rt<<1].tag+=tr[rt].tag;tr[rt<<1].sum+=tr[rt].tag*(tr[rt<<1].r-tr[rt<<1].l+1);tr[rt<<1|1].tag+=tr[rt].tag;tr[rt<<1|1].sum+=tr[rt].tag*(tr[rt<<1|1].r-tr[rt<<1|1].l+1);tr[rt].tag=0;return;
}void build(int rt,int l,int r){tr[rt].l=l;tr[rt].r=r;if(l==r){tr[rt].sum=a[real[l]];return;}int mid=(l+r)>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);pushup(rt);
}void update(int now,int ll,int rr,int x){if(ll<=tr[now].l&&tr[now].r<=rr){tr[now].sum+=(tr[now].r-tr[now].l+1)*x;tr[now].tag+=x;return;}pushdown(now);int mid=(tr[now].l+tr[now].r)>>1;if(rr<=mid)update(now<<1,ll,rr,x);else if(ll>mid)update(now<<1|1,ll,rr,x);else {update(now<<1,ll,mid,x);update(now<<1|1,mid+1,rr,x);}pushup(now);//***
}
LL query_sum(int now,int ll,int rr){if(ll<=tr[now].l&&tr[now].r<=rr){return tr[now].sum;}pushdown(now);int mid=(tr[now].l+tr[now].r)>>1;if(rr<=mid)return query_sum(now<<1,ll,rr);else if(ll>mid)return query_sum(now<<1|1,ll,rr);else{return query_sum(now<<1,ll,mid)+query_sum(now<<1|1,mid+1,rr);}
}
void change(int u,int v,LL x){int tu=top[u],tv=top[v];while(tu!=tv){if(depth[tu]<depth[tv]){swap(tu,tv);swap(u,v);}update(1,id[tu],id[u],x);u=dad[tu];tu=top[u];}if(depth[u]>depth[v])swap(u,v);update(1,id[u],id[v],x);
}
int find_sum(int u,int v){LL sum=0;int tu=top[u],tv=top[v];while(tu!=tv){if(depth[tu]<depth[tv]){swap(tu,tv);swap(u,v);}sum+=query_sum(1,id[tu],id[u]);sum%=mod;u=dad[tu];tu=top[u];}if(depth[u]>depth[v])swap(u,v);sum+=query_sum(1,id[u],id[v]);return sum%mod;
}void root_add(int now,LL x){int begin=id[now];int ed=id[now]+son[now]-1;update(1,begin,ed,x);
}
LL root_sum(int now){int begin=id[now];int ed=id[now]+son[now]-1;return query_sum(1,begin,ed)%mod;
}int main(){scanf("%d%d%d%lld",&n,&m,&r,&mod);for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=1;i<n;i++){scanf("%d%d",&u,&v);add(u,v);add(v,u);}dfs1(r,0);dfs2(r,r);build(1,1,temp);for(int i=0;i<m;i++){int t,x,y,z;scanf("%d",&t);if(t==1){scanf("%d%d%d",&x,&y,&z);change(x,y,z);}else if(t==2){scanf("%d%d",&x,&y);printf("%lld\n",find_sum(x,y));}else if(t==3){scanf("%d%d",&x,&y);root_add(x,y);}else if(t==4){scanf("%d",&x);printf("%lld\n",root_sum(x));}}return 0;
} 

转载于:https://www.cnblogs.com/zzyh/p/7421203.html

P3384 【模板】树链剖分相关推荐

  1. 【模板】树链剖分 P3384

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

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

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

  3. 洛谷P3384 - 树链剖分(树链剖分模板题)

    题目链接 https://www.luogu.org/problemnew/show/P3384 [描述] 树链剖分模板题,记一下板子 #include<bits/stdc++.h> #d ...

  4. 专题·树链剖分【including 洛谷·【模板】树链剖分

    初见安~~~终于学会了树剖~~~ [兴奋]当初机房的大佬在学树剖的时候我反复强调过:"学树剖没有前途的!!!" 恩.真香. 一.重链与重儿子 所谓树剖--树链剖分,就是赋予一个链的 ...

  5. 洛谷3384:【模板】树链剖分——题解

    https://www.luogu.org/problemnew/show/P3384 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 ...

  6. 模板 - 图论 - 树链剖分

    今天来啃一下这个树剖吧. 模板题是要求这四个问题: 将树从x到y结点最短路径上所有节点的值都加上z 求树从x到y结点最短路径上所有节点的值之和 将以x为根节点的子树内所有节点值都加上z 求以x为根节点 ...

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

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

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

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

  9. 【高级数据结构】[SPOJ QTREE]树链剖分/动态树各一模板

    题目: 树链剖分: #include<cstdio> #include<cstring> #include<algorithm> using namespace s ...

  10. 洛谷3384(树链剖分模板题)

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

最新文章

  1. (C++)1025 PAT Ranking
  2. NodeJS学习之网络操作
  3. 【crontab】误删crontab及其恢复
  4. THE TOP FILE(top文件详解)
  5. 像素级动态模糊(Pixel Motion Blur)
  6. [NOIP2016 提高组] 愤怒的小鸟
  7. 【连载】人类唯一的出路:变成人工智能(二)脑机接口
  8. Win10下Eclipse运行环境的安装
  9. arcpy 基于python制作六十进制与十进制互换的工具箱
  10. 使用计算机音箱进行音乐播放的过程,插卡音箱音乐播放顺序调整及歌单式1
  11. python3视频教程哪个好_python3入门视频教程
  12. java 发卡平台支付_基于jsp的自动发卡平台-JavaEE实现自动发卡平台 - java项目源码...
  13. 计算机游戏测试软件,你的电脑能不能吃鸡,两款软件很简单就能测试出来
  14. buuctf XCTF October 2019 Twice SQL Injection 二次注入原理+题解
  15. dubbo服务暴露与注册
  16. RLC谐振电路简单计算公式
  17. 我是如何让公司后台管理系统焕然一新的(上) -性能优化
  18. 网络传输介质 通信中的有线介质:双绞线、同轴电缆、光纤 引导性传输介质
  19. Fast R-CNN 论文详读
  20. eclipse项目感叹号

热门文章

  1. keras 多层lstm_《Keras 实现 LSTM》笔记
  2. python调用rust_转 从20秒到0.5秒:一个使用Rust语言来优化Python性能的案例
  3. 世界公认最好的记忆方法_毕业清单日签 I 世界公认最好的学习方法,没有之一。...
  4. 【SpringBoot】【Thyemeleaf 】【Spring EL表达式】 SPEL调用静态类、静态方法
  5. mysql查询建表SQL语句
  6. 【spring boot】新建项目,实现HelloWorld
  7. python输入文件名读取文件_[Python] python3 文件操作:从键盘输入、打开关闭文件、读取写入文件、重命名与删除文件等...
  8. pythonsocket数据对接_python socket通信 网站之间数据交流
  9. 在日常办公能做什么_日常生活中电烤箱能烤制什么美食呢?
  10. 二十七、综合案例数据预处理