洛谷P3384 树链剖分
如题,已知一棵包含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为根节点的子树内所有节点值之和
--by洛谷
一听名字就知道是模板;
有关树链剖分的内容
对子树操作,可理解为对dfs序上fa开头长度为子树size的区间操作;
代码如下:
1 #include<cstdio> 2 using namespace std; 3 int n,m,r,L,R; 4 int p,Z; 5 int dis[100001]; 6 int ltree[400001]; 7 int lz[400001]; 8 int dep[100001],fa[100001],hine[100001],size[100001]; 9 int top[100001],a[100001],rank[100001]; 10 struct ss{ 11 int to,next; 12 }x[200001]; 13 int first[200001],num; 14 void build(int ,int ); 15 void dfs_1(int ); 16 void dfs_2(int ,int ); 17 void up(int ); 18 void down(int ,int ,int ); 19 void builine(int ,int ,int ); 20 void swap(int&,int&); 21 void work1(int ); 22 void work2(int ); 23 void add(int ,int ,int ); 24 int sum(int ,int ,int ); 25 int main() 26 { 27 int i,j,k; 28 scanf("%d%d%d%d",&n,&m,&r,&p); 29 for(i=1;i<=n;i++) 30 scanf("%d",&dis[i]),dis[i]%=p,hine[i]=i; 31 for(i=1;i<=n-1;i++){ 32 scanf("%d%d",&j,&k); 33 build(j,k); 34 build(k,j); 35 } 36 dep[r]=1; 37 dfs_1(r); 38 num=0; 39 dfs_2(r,r); 40 num=0; 41 builine(1,n,1); 42 for(i=1;i<=m;i++){ 43 scanf("%d",&j); 44 if(j<=2)work1(j); 45 else work2(j-2); 46 } 47 } 48 void build(int f,int t){ 49 x[++num].next=first[f]; 50 x[num].to=t; 51 first[f]=num; 52 } 53 void dfs_1(int now){ 54 int j=first[now]; 55 while(j){ 56 if(!dep[x[j].to]){ 57 dep[x[j].to]=dep[now]+1; 58 fa[x[j].to]=now; 59 dfs_1(x[j].to); 60 size[now]+=size[x[j].to]; 61 if(hine[now]==now||size[x[j].to]>size[hine[now]]) 62 hine[now]=x[j].to; 63 } 64 j=x[j].next; 65 } 66 size[now]++; 67 } 68 void dfs_2(int now,int top_now){ 69 int j=first[now]; 70 top[now]=top_now; 71 a[++num]=now; 72 rank[now]=num; 73 if(hine[now]!=now) 74 dfs_2(hine[now],top_now); 75 while(j){ 76 if(dep[x[j].to]==dep[now]+1&&x[j].to!=hine[now]) 77 dfs_2(x[j].to,x[j].to); 78 j=x[j].next; 79 } 80 } 81 void up(int nu){ 82 ltree[nu]=ltree[nu<<1]+ltree[nu<<1|1]; 83 } 84 void down(int l,int r,int nu){ 85 if(!lz[nu])return ; 86 int mid=(l+r)>>1; 87 lz[nu<<1]=(lz[nu<<1]+lz[nu])%p; 88 lz[nu<<1|1]=(lz[nu<<1|1]+lz[nu])%p; 89 ltree[nu<<1]=(ltree[nu<<1]+lz[nu]*(mid-l+1))%p; 90 ltree[nu<<1|1]=(ltree[nu<<1|1]+lz[nu]*(r-mid))%p; 91 lz[nu]=0; 92 } 93 void builine(int l,int r,int nu){ 94 if(l==r){ 95 ltree[nu]=dis[a[++num]]; 96 return; 97 } 98 int mid=(l+r)>>1; 99 builine(l,mid,nu<<1); 100 builine(mid+1,r,nu<<1|1); 101 up(nu); 102 } 103 void swap(int&a,int&b){ 104 int c=a;a=b;b=c; 105 } 106 void work1(int x){ 107 int u,v,ans=0; 108 scanf("%d%d",&u,&v); 109 if(x==1)scanf("%d",&Z); 110 while(top[u]!=top[v]){ 111 if(dep[top[u]]>dep[top[v]]) 112 L=rank[top[u]],R=rank[u],u=fa[top[u]]; 113 else 114 L=rank[top[v]],R=rank[v],v=fa[top[v]]; 115 if(x==1) 116 add(1,n,1); 117 else 118 ans=(ans+sum(1,n,1))%p; 119 } 120 // if(u!=v){121 if(dep[u]>dep[v]) 122 swap(u,v); 123 L=rank[u];R=rank[v]; 124 if(x==1) 125 add(1,n,1); 126 else 127 ans=(ans+sum(1,n,1))%p; 128 // } 129 if(x==2) 130 printf("%d\n",ans); 131 } 132 void work2(int x){ 133 int ans=0,i; 134 scanf("%d",&i); 135 L=rank[i];R=L+size[i]-1; 136 if(x==1)scanf("%d",&Z); 137 if(x==1) 138 add(1,n,1); 139 else 140 ans=(ans+sum(1,n,1))%p,printf("%d\n",ans); 141 } 142 void add(int l,int r,int nu){ 143 if(L<=l&&r<=R){ 144 ltree[nu]=(ltree[nu]+(r-l+1)*Z)%p; 145 lz[nu]=(lz[nu]+Z)%p; 146 return ; 147 } 148 int mid=(l+r)>>1; 149 down(l,r,nu); 150 if(L<=mid) 151 add(l,mid,nu<<1); 152 if(R>mid) 153 add(mid+1,r,nu<<1|1); 154 up(nu); 155 } 156 int sum(int l,int r,int nu){ 157 if(L<=l&&r<=R) 158 return ltree[nu]; 159 int mid=(l+r)>>1,ans=0; 160 down(l,r,nu); 161 if(L<=mid) 162 ans=(ans+sum(l,mid,nu<<1))%p; 163 if(R>mid) 164 ans=(ans+sum(mid+1,r,nu<<1|1))%p; 165 return ans; 166 }
祝AC哟!
转载于:https://www.cnblogs.com/nietzsche-oier/p/6386278.html
洛谷P3384 树链剖分相关推荐
- 洛谷P3384 - 树链剖分(树链剖分模板题)
题目链接 https://www.luogu.org/problemnew/show/P3384 [描述] 树链剖分模板题,记一下板子 #include<bits/stdc++.h> #d ...
- 洛谷树剖模板题 P3384 | 树链剖分
原题链接 对于以u为根的子树,后代节点的dfn显然比他的dfn大,我们可以记录一下回溯到u的dfn,显然这两个dfn构成了一个连续区间,代表u及u的子树 剩下的就和树剖一样了 1 #include&l ...
- 【luogu P3384 树链剖分】 模板
题目链接:https://www.luogu.org/problemnew/show/P3384 诶又给自己留了个坑..不想写线段树一大理由之前的模板变量名太长 #include <cstdio ...
- 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释...
P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...
- 专题·树链剖分【including 洛谷·【模板】树链剖分
初见安~~~终于学会了树剖~~~ [兴奋]当初机房的大佬在学树剖的时候我反复强调过:"学树剖没有前途的!!!" 恩.真香. 一.重链与重儿子 所谓树剖--树链剖分,就是赋予一个链的 ...
- ⌈洛谷1505⌋⌈BZOJ2157⌋⌈国家集训队⌋旅游【树链剖分】
题目链接 [洛谷] [BZOJ] 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T ...
- 洛谷3384:【模板】树链剖分——题解
https://www.luogu.org/problemnew/show/P3384 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 ...
- 洛谷3384(树链剖分模板题)
题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...
- 【树链剖分】洛谷树(P3401)
正题 P3401 题目大意 给你一棵树,让你进行以下操作 修改一条边的边权 查询一条路径的所有子路径异或值的和 解题思路 记下所有点到根节点的路径亦或值,那么查询就是所有点对的异或值之和 因为边权&l ...
- 洛谷P2486 [SDOI2011]染色(树链剖分+线段树判断边界)
[题目链接] [思路]: 涉及到树上区间修改操作,所以使用树链剖分,涉及到区间查询,所以使用线段树. update操作时,就正常操作,难点在于query操作的计数. 因为树链剖分的dfs序只能保证一条 ...
最新文章
- 2560x1600分辨率高吗_手机屏幕分辨率真的越高越好?它的好处和坏处你知道吗?...
- android界面布局题,【填空题】Android 系统中, 用于定义布局显示在界面上的风格。...
- 口袋操作系统_可以装进口袋的主机要有多小?驰为LarBox迷你主机入手体验
- hadoop启动报错:localhost: ssh: Could not resolve hostname localhost
- 95-080-058-源码-启动-启动taskexecutor
- Sublime text 3 SVN插件及使用方法
- SQLite性能提升10倍的Web数据库
- 未解决的问题记录——关于easyui中datagrid的冻结列右侧冻结
- Eclipse编辑HTML,JSP,JS等时的卡顿问题,非常有效!!!
- [转] Spring XML配置十二个最佳实践
- DirectFB简介以及移植[一]【转】
- Python学习-第三天-面向对象编程基础
- PHP 5 echo 和 print 语句
- nginx访问php文件an error occurred,nginx提示 An error occurred错误问题解决办法
- 火狐不能html转execl,使用Blob无法在FireFox中使用Excel导出JavaScript
- CCCC 天梯赛 PTA ZOJ 题目 L1 L2 L3
- 【小技巧】Linux安装matlab教程
- NTU RGB+D动作识别数据集
- 树莓派python3的opencv下载(编译失败第六步必看)
- 第三次全国土地调查拉开了帷幕