题目描述

如题,已知一棵包含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:

  1. 5 5 2 24
  2. 7 3 7 8 0
  3. 1 2
  4. 1 5
  5. 3 1
  6. 4 1
  7. 3 4 2
  8. 3 2 2
  9. 4 5
  10. 1 5 1 3
  11. 2 1 3
输出样例#1:

  1. 2
  2. 21

说明

时空限制:1s,128M

数据规模:

对于30%的数据:N<=10,M<=10

对于70%的数据:N<=1000,M<=1000

对于100%的数据:N<=100000,M<=100000

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

样例说明:

树的结构如下:

各个操作如下:

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

思路:

  裸树剖;

来,上代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5.  
  6. #define maxn 100001
  7. #define LL long long int
  8.  
  9. using namespace std;
  10.  
  11. struct EdgeType {
  12. LL to,next;
  13. };
  14. struct EdgeType edge[maxn<<];
  15.  
  16. struct TreeNodeType {
  17. LL l,r,dis,mid,flag;
  18. };
  19. struct TreeNodeType tree[maxn<<];
  20.  
  21. LL if_z,tree_num,tree_dis[maxn],deep[maxn],cnt;
  22. LL f[maxn],n,m,s,p,dis[maxn],flag[maxn],Enum;
  23. LL size[maxn],end[maxn],belong[maxn],head[maxn];
  24.  
  25. char Cget;
  26.  
  27. inline void read_int(LL &now)
  28. {
  29. now=,if_z=,Cget=getchar();
  30. while(Cget>''||Cget<'')
  31. {
  32. if(Cget=='-') if_z=-;
  33. Cget=getchar();
  34. }
  35. while(Cget>=''&&Cget<='')
  36. {
  37. now=now*+Cget-'';
  38. Cget=getchar();
  39. }
  40. now*=if_z;
  41. }
  42.  
  43. inline void edge_add(LL from,LL to)
  44. {
  45. edge[++Enum].to=from,edge[Enum].next=head[to],head[to]=Enum;
  46. edge[++Enum].to=to,edge[Enum].next=head[from],head[from]=Enum;
  47. }
  48.  
  49. inline void tree_up(LL now)
  50. {
  51. tree[now].dis=tree[now<<].dis+tree[now<<|].dis;
  52. }
  53.  
  54. void tree_build(LL now,LL l,LL r)
  55. {
  56. tree[now].l=l,tree[now].r=r;
  57. if(l==r)
  58. {
  59. tree[now].dis=tree_dis[++tree_num];
  60. return ;
  61. }
  62. tree[now].mid=(tree[now].l+tree[now].r)>>;
  63. tree_build(now<<,l,tree[now].mid);
  64. tree_build(now<<|,tree[now].mid+,r);
  65. tree_up(now);
  66. }
  67.  
  68. inline void tree_down(LL now)
  69. {
  70. if(tree[now].l==tree[now].r) return ;
  71. tree[now<<].dis+=(tree[now<<].r-tree[now<<].l+)*tree[now].flag;
  72. tree[now<<].flag+=tree[now].flag;
  73. tree[now<<|].dis+=(tree[now<<|].r-tree[now<<|].l+)*tree[now].flag;
  74. tree[now<<|].flag+=tree[now].flag;
  75. tree[now].flag=;
  76. }
  77.  
  78. void tree_change(LL now,LL l,LL r,LL x)
  79. {
  80. if(tree[now].l==l&&tree[now].r==r)
  81. {
  82. tree[now].dis+=(r-l+)*x;
  83. tree[now].flag+=x;
  84. return ;
  85. }
  86. if(tree[now].flag) tree_down(now);
  87. if(l>tree[now].mid) tree_change(now<<|,l,r,x);
  88. else if(r<=tree[now].mid) tree_change(now<<,l,r,x);
  89. else
  90. {
  91. tree_change(now<<,l,tree[now].mid,x);
  92. tree_change(now<<|,tree[now].mid+,r,x);
  93. }
  94. tree_up(now);
  95. }
  96.  
  97. LL tree_query(LL now,LL l,LL r)
  98. {
  99. if(tree[now].l==l&&tree[now].r==r)
  100. {
  101. return tree[now].dis;
  102. }
  103. if(tree[now].flag) tree_down(now);
  104. tree_up(now);
  105. if(l>tree[now].mid) return tree_query(now<<|,l,r);
  106. else if(r<=tree[now].mid) return tree_query(now<<,l,r);
  107. else return tree_query(now<<,l,tree[now].mid)+tree_query(now<<|,tree[now].mid+,r);
  108. }
  109.  
  110. void search(LL now,LL fa)
  111. {
  112. LL pos=cnt++;
  113. deep[now]=deep[fa]+,f[now]=fa;
  114. for(LL i=head[now];i;i=edge[i].next)
  115. {
  116. if(edge[i].to==fa) continue;
  117. search(edge[i].to,now);
  118. }
  119. size[now]=cnt-pos;
  120. }
  121.  
  122. void search_(LL now,LL chain)
  123. {
  124. belong[now]=chain,flag[now]=++cnt;
  125. tree_dis[flag[now]]=dis[now];
  126. LL pos=;
  127. for(LL i=head[now];i;i=edge[i].next)
  128. {
  129. if(flag[edge[i].to]!=) continue;
  130. if(size[edge[i].to]>size[pos]) pos=edge[i].to;
  131. }
  132. if(pos!=) search_(pos,chain);
  133. for(LL i=head[now];i;i=edge[i].next)
  134. {
  135. if(flag[edge[i].to]!=) continue;
  136. search_(edge[i].to,edge[i].to);
  137. }
  138. end[now]=cnt;
  139. }
  140.  
  141. inline void solve_change(LL x,LL y,LL z)
  142. {
  143. while(belong[x]!=belong[y])
  144. {
  145. if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
  146. tree_change(,flag[belong[x]],flag[x],z);
  147. x=f[belong[x]];
  148. }
  149. if(deep[x]<deep[y]) swap(x,y);
  150. tree_change(,flag[y],flag[x],z);
  151. }
  152.  
  153. inline LL solve_query(LL x,LL y)
  154. {
  155. LL ans=;
  156. while(belong[x]!=belong[y])
  157. {
  158. if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
  159. ans=(ans+tree_query(,flag[belong[x]],flag[x]))%p;
  160. x=f[belong[x]];
  161. }
  162. if(deep[x]<deep[y]) swap(x,y);
  163. ans=(ans+tree_query(,flag[y],flag[x]))%p;
  164. return ans;
  165. }
  166.  
  167. int main()
  168. {
  169. read_int(n),read_int(m),read_int(s),read_int(p);
  170. for(LL i=;i<=n;i++) read_int(dis[i]);
  171. LL type,from,to,cur;
  172. for(LL i=;i<n;i++)
  173. {
  174. read_int(from),read_int(to);
  175. edge_add(from,to);
  176. }
  177. search(s,),cnt=,search_(s,s);
  178. cnt=,tree_build(,,n);
  179. for(LL i=;i<=m;i++)
  180. {
  181. read_int(type);
  182. if(type==)
  183. {
  184. read_int(from),read_int(to),read_int(cur);
  185. solve_change(from,to,cur);
  186. }
  187. if(type==)
  188. {
  189. read_int(from),read_int(to);
  190. printf("%d\n",solve_query(from,to)%p);
  191. }
  192. if(type==)
  193. {
  194. read_int(from),read_int(to);
  195. tree_change(,flag[from],end[from],to);
  196. }
  197. if(type==)
  198. {
  199. read_int(from);
  200. printf("%d\n",tree_query(,flag[from],end[from])%p);
  201. }
  202. }
  203. return ;
  204. }

AC日记——【模板】树链剖分 洛谷 P3384的更多相关文章

  1. [luogu P3384] [模板]树链剖分

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

  2. luoguP3384 [模板]树链剖分

    luogu P3384 [模板]树链剖分 题目 #include<iostream> #include<cstdlib> #include<cstdio> #inc ...

  3. [洛谷P3384] [模板] 树链剖分

    题目传送门 显然是一道模板题. 然而索引出现了错误,狂wa不止. 感谢神犇Dr_J指正.%%%orz. 建线段树的时候,第44行. 把sum[p]=bv[pos[l]]%mod;打成了sum[p]=b ...

  4. 模板 树链剖分BFS版本

    //点和线段树都从1开始 //边使用vector vector<int> G[maxn]; ],num[maxn],iii[maxn],b[maxn],a[maxn],top[maxn], ...

  5. AC日记——红色的幻想乡 洛谷 P3801

    红色的幻想乡 思路: 线段树+容斥原理: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #de ...

  6. AC日记——无线网络发射器选址 洛谷 P2038

    题目描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的129 条东西向街道和129 条南北向街道所形成的网格状,并且相邻 ...

  7. AC日记——小A的糖果 洛谷七月月赛

    小A的糖果 思路: for循环贪心: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #defi ...

  8. AC日记——矩阵取数游戏 洛谷 P1005

    矩阵取数游戏 思路: dp+高精: 代码: #include <bits/stdc++.h> using namespace std; #define ll long long struc ...

  9. AC日记——妖梦拼木棒 洛谷 P3799

    妖梦拼木棒 思路: 神特么题: 代码: #include <bits/stdc++.h> using namespace std; #define mod 1000000007LL int ...

随机推荐

  1. 使用JFreeChart生成报表

    1.JFreeChart简介    JFreeChart是JAVA平台上的一个开放的图表绘制类库.它完全使用JAVA语言编写,是为applications,servlets以及JSP等使用所设计.  ...

  2. HDU 6156 回文 数位DP(2017CCPC)

    Palindrome Function Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Ot ...

  3. WebView的初体验

    使用安卓自带控件可以实现不通过浏览器即可上网的功能 突然就觉得安卓好强大,是不是我太无知了,太容易满足了 1.在layout中添加VebView控件 2.在Activity中设置WebView的属性 ...

  4. 10,Scrapy简单入门及实例讲解

    Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以 ...

  5. 1 django

    1.MVC 大部分开发语言中都有MVC框架 MVC框架的核心思想是:解耦 降低各功能模块之间的耦合性,方便变更,更容易重构代码,最大程度上实现代码的重用 m表示model,主要用于对数据库层的封装 v ...

  6. 4 Template层 -定义模板

    1.模板介绍 作为Web框架,Django提供了模板,可以很便利的动态生成HTML 模版系统致力于表达外观,而不是程序逻辑 模板的设计实现了业务逻辑(view)与显示内容(template)的分离,一 ...

  7. P1616 疯狂的采药

    P1616 疯狂的采药 题目背景 此题为NOIP2005普及组第三题的疯狂版. 此题为纪念LiYuxiang而生. 题目描述 LiYuxiang是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师.为 ...

  8. jq相关细节-1

    animate/动画 所有用于动画的属性必须是数字的,除非另有说明:这些属性如果不是数字的将不能使用基本的jQuery功能.(例如,width, height或者left可以执行动画,但是backgr ...

  9. 1、IOS学习计划

    2015年12月10日 -- 2015年12月27日(一共3个周末,12个个工作日) 1.斯坦福公开课(IOS7应用开发) 一共18节课程,通过视频和demo建立感觉 2.千峰的OC课程 一共25节课 ...

  10. 【BZOJ 3620】似乎在梦中见过的样子

    题目 (夢の中で逢った.ような--) 「Madoka,不要相信 QB!」伴随着 Homura 的失望地喊叫,Madoka 与 QB 签订了契约. 这是 Modoka 的一个噩梦,也同时是上个轮回中所发 ...