P3384 【模板】树链剖分
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取模)
输入输出样例
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
2 21
说明
时空限制:1s,128M
数据规模:
对于30%的数据: N \leq 10, M \leq 10N≤10,M≤10
对于70%的数据: N \leq {10}^3, M \leq {10}^3N≤103,M≤103
对于100%的数据: N \leq {10}^5, M \leq {10}^5N≤105,M≤105
( 其实,纯随机生成的树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 【模板】树链剖分相关推荐
- 【模板】树链剖分 P3384
题目链接 //部分转自:https://www.luogu.org/problemnew/solution/P3384 初学树链剖分,感觉这个模板题还是容易理解的,但是实在是码量很大的. 知识点: 重 ...
- 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释...
P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...
- 洛谷P3384 - 树链剖分(树链剖分模板题)
题目链接 https://www.luogu.org/problemnew/show/P3384 [描述] 树链剖分模板题,记一下板子 #include<bits/stdc++.h> #d ...
- 专题·树链剖分【including 洛谷·【模板】树链剖分
初见安~~~终于学会了树剖~~~ [兴奋]当初机房的大佬在学树剖的时候我反复强调过:"学树剖没有前途的!!!" 恩.真香. 一.重链与重儿子 所谓树剖--树链剖分,就是赋予一个链的 ...
- 洛谷3384:【模板】树链剖分——题解
https://www.luogu.org/problemnew/show/P3384 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 ...
- 模板 - 图论 - 树链剖分
今天来啃一下这个树剖吧. 模板题是要求这四个问题: 将树从x到y结点最短路径上所有节点的值都加上z 求树从x到y结点最短路径上所有节点的值之和 将以x为根节点的子树内所有节点值都加上z 求以x为根节点 ...
- 树链剖分概念及模板 + 例题 [POJ3237 tree + 软件包管理器]
文章目录 概念 模板 例题1:软件包管理器 题目 题解 代码实现 例题2:POJ3237 tree 题目 题解 代码实现 概念 树链剖分主要是用于解决以下这两个问题. 1.更改树上点x到点y的最短路径 ...
- 树链剖分 讲解+模板+习题
今天我们来讲一下树链剖分 树链剖分是什么? 树链剖分是一种用来维护树上路径信息的在线方法,可以处理在线. 通常通过一种方法,将一棵树剖分成若干条链,然后通过数据结构(线段树,BIT等)去维护. 我们通 ...
- 【高级数据结构】[SPOJ QTREE]树链剖分/动态树各一模板
题目: 树链剖分: #include<cstdio> #include<cstring> #include<algorithm> using namespace s ...
- 洛谷3384(树链剖分模板题)
题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...
最新文章
- (C++)1025 PAT Ranking
- NodeJS学习之网络操作
- 【crontab】误删crontab及其恢复
- THE TOP FILE(top文件详解)
- 像素级动态模糊(Pixel Motion Blur)
- [NOIP2016 提高组] 愤怒的小鸟
- 【连载】人类唯一的出路:变成人工智能(二)脑机接口
- Win10下Eclipse运行环境的安装
- arcpy 基于python制作六十进制与十进制互换的工具箱
- 使用计算机音箱进行音乐播放的过程,插卡音箱音乐播放顺序调整及歌单式1
- python3视频教程哪个好_python3入门视频教程
- java 发卡平台支付_基于jsp的自动发卡平台-JavaEE实现自动发卡平台 - java项目源码...
- 计算机游戏测试软件,你的电脑能不能吃鸡,两款软件很简单就能测试出来
- buuctf XCTF October 2019 Twice SQL Injection 二次注入原理+题解
- dubbo服务暴露与注册
- RLC谐振电路简单计算公式
- 我是如何让公司后台管理系统焕然一新的(上) -性能优化
- 网络传输介质 通信中的有线介质:双绞线、同轴电缆、光纤 引导性传输介质
- Fast R-CNN 论文详读
- eclipse项目感叹号
热门文章
- keras 多层lstm_《Keras 实现 LSTM》笔记
- python调用rust_转 从20秒到0.5秒:一个使用Rust语言来优化Python性能的案例
- 世界公认最好的记忆方法_毕业清单日签 I 世界公认最好的学习方法,没有之一。...
- 【SpringBoot】【Thyemeleaf 】【Spring EL表达式】 SPEL调用静态类、静态方法
- mysql查询建表SQL语句
- 【spring boot】新建项目,实现HelloWorld
- python输入文件名读取文件_[Python] python3 文件操作:从键盘输入、打开关闭文件、读取写入文件、重命名与删除文件等...
- pythonsocket数据对接_python socket通信 网站之间数据交流
- 在日常办公能做什么_日常生活中电烤箱能烤制什么美食呢?
- 二十七、综合案例数据预处理