这个题是一个经典的维护路径信息的题,对于路径上的修改,我们只需要把对应的链\(split\)上来,然后修改最上面的点就好,注意pushdown的时候的顺序是先乘后加

然后下传乘法标记的时候,记得把对应的\(add\)标记也要乘,因为就跟线段树的下传标记类似

  1. // luogu-judger-enable-o2
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<vector>
  7. #include<queue>
  8. #include<cmath>
  9. #include<map>
  10. #include<set>
  11. #define int long long
  12. using namespace std;
  13. inline int read()
  14. {
  15. int x=0,f=1;char ch=getchar();
  16. while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
  17. while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  18. return x*f;
  19. }
  20. const int maxn = 1e5+1e2;
  21. const int mod = 51061;
  22. int ch[maxn][3];
  23. int n,m;
  24. int sum[maxn],val[maxn];
  25. int che[maxn],add[maxn];
  26. int fa[maxn],size[maxn];
  27. int st[maxn];
  28. int rev[maxn];
  29. int son(int x)
  30. {
  31. if (ch[fa[x]][0]==x) return 0;
  32. else return 1;
  33. }
  34. bool notroot(int x)
  35. {
  36. return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
  37. }
  38. void update(int x)
  39. {
  40. size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
  41. sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+val[x])%mod;
  42. }
  43. void reverse(int x)
  44. {
  45. swap(ch[x][0],ch[x][1]);
  46. rev[x]^=1;
  47. }
  48. void jia(int x,int d)
  49. {
  50. sum[x]+=size[x]*d;
  51. sum[x]%=mod;
  52. val[x]+=d;
  53. val[x]%=mod;
  54. add[x]+=d;
  55. add[x]%=mod;
  56. }
  57. void cheng(int x,int d)
  58. {
  59. sum[x]*=d;
  60. sum[x]%=mod;
  61. val[x]*=d;
  62. val[x]%=mod;
  63. add[x]*=d;
  64. add[x]%=mod;
  65. che[x]*=d;
  66. che[x]%=mod;
  67. }
  68. void pushdown(int x)
  69. {
  70. if (che[x]!=1)
  71. {
  72. if (ch[x][0]) cheng(ch[x][0],che[x]);
  73. if (ch[x][1]) cheng(ch[x][1],che[x]);
  74. che[x]=1;
  75. }
  76. if (add[x])
  77. {
  78. if (ch[x][0]) jia(ch[x][0],add[x]);
  79. if (ch[x][1]) jia(ch[x][1],add[x]);
  80. add[x]=0;
  81. }
  82. if (rev[x])
  83. {
  84. if (ch[x][0]) reverse(ch[x][0]);
  85. if (ch[x][1]) reverse(ch[x][1]);
  86. rev[x]=0;
  87. }
  88. }
  89. void rotate(int x)
  90. {
  91. int y=fa[x],z=fa[y];
  92. int b=son(x),c=son(y);
  93. if (notroot(y)) ch[z][c]=x;
  94. fa[x]=z;
  95. ch[y][b]=ch[x][!b];
  96. fa[ch[x][!b]]=y;
  97. ch[x][!b]=y;
  98. fa[y]=x;
  99. update(y);
  100. update(x);
  101. }
  102. void splay(int x)
  103. {
  104. int y=x,cnt=0;
  105. st[++cnt]=y;
  106. while (notroot(y)) y=fa[y],st[++cnt]=y;
  107. while (cnt) pushdown(st[cnt--]);
  108. while (notroot(x))
  109. {
  110. int y=fa[x],z=fa[y];
  111. int b=son(x),c=son(y);
  112. if (notroot(y))
  113. {
  114. if (b==c) rotate(y);
  115. else rotate(x);
  116. }
  117. rotate(x);
  118. }
  119. update(x);
  120. }
  121. void access(int x)
  122. {
  123. for (int y=0;x;y=x,x=fa[x])
  124. {
  125. splay(x);
  126. ch[x][1]=y;
  127. update(x);
  128. }
  129. }
  130. void makeroot(int x)
  131. {
  132. access(x);
  133. splay(x);
  134. reverse(x);
  135. }
  136. int findroot(int x)
  137. {
  138. access(x);
  139. splay(x);
  140. while (ch[x][0])
  141. {
  142. pushdown(x);
  143. x=ch[x][0];
  144. }
  145. return x;
  146. }
  147. void split(int x,int y)
  148. {
  149. makeroot(x);
  150. access(y);
  151. splay(y);
  152. }
  153. void link(int x,int y)
  154. {
  155. makeroot(x);
  156. if (findroot(y)!=x) fa[x]=y;
  157. }
  158. void cut(int x,int y)
  159. {
  160. split(x,y);
  161. if (ch[x][0] || ch[x][1] || fa[x]!=y || ch[y][son(x)^1]) return;
  162. fa[x]=ch[y][0]=0;
  163. }
  164. char s[10];
  165. signed main()
  166. {
  167. n=read(),m=read();
  168. for (int i=1;i<=n;i++) che[i]=1,add[i]=0,val[i]=1;
  169. for (int i=1;i<n;i++)
  170. {
  171. int x=read(),y=read();
  172. link(x,y);
  173. }
  174. //split(1,3);
  175. //cout<<sum[3]<<endl;
  176. for(int i=1;i<=m;i++)
  177. {
  178. scanf("%s",s+1);
  179. if (s[1]=='+')
  180. {
  181. int x=read(),y=read(),z=read();
  182. split(x,y);
  183. val[y]+=z;
  184. val[y]%=mod;
  185. sum[y]+=size[y]*z;
  186. sum[y]%=mod;
  187. add[y]+=z;
  188. add[y]%=mod;
  189. }
  190. else
  191. if (s[1]=='-')
  192. {
  193. int x=read(),y=read(),xx=read(),yy=read();
  194. cut(x,y);
  195. link(xx,yy);
  196. }
  197. else
  198. if (s[1]=='/')
  199. {
  200. int x=read(),y=read();
  201. split(x,y);
  202. printf("%lld\n",sum[y]%mod);
  203. }
  204. else
  205. {
  206. int x=read(),y=read(),z=read();
  207. //cout<<z<<endl;
  208. split(x,y);
  209. sum[y]*=z;
  210. sum[y]%=mod;
  211. val[y]*=z;
  212. val[y]%=mod;
  213. add[y]*=z;
  214. add[y]%=mod;
  215. che[y]*=z;
  216. che[y]%=mod;
  217. }
  218. }
  219. return 0;
  220. }

洛谷1501 Tree II(LCT,路径修改,路经询问)的更多相关文章

  1. 洛谷P1501 Tree II

    LCT 还是LCT的板子,下放标记和那道线段树2一样,先放乘..之前用char忘记getchar,调了好久... 注意开long long!! #include <bits/stdc++.h&g ...

  2. 【洛谷1501】[国家集训队] Tree II(LCT维护懒惰标记)

    点此看题面 大致题意: 有一棵初始边权全为\(1\)的树,四种操作:将两点间路径边权都加上一个数,删一条边.加一条新边,将两点间路径边权都加上一个数,询问两点间路径权值和. 序列版 这道题有一个序列版 ...

  3. 点分治模板(洛谷P4178 Tree)(树分治,树的重心,容斥原理)

    推荐YCB的总结 推荐你谷ysn等巨佬的详细题解 大致流程-- dfs求出当前树的重心 对当前树内经过重心的路径统计答案(一条路径由两条由重心到其它点的子路径合并而成) 容斥减去不合法情况(两条子路径 ...

  4. 洛谷 P2764 LibreOJ 6002 最小路径覆盖问题

    题目描述 «问题描述: 给定有向图G=(V,E).设P 是G 的一个简单路(顶点不相交)的集合.如果V 中每个顶点恰好在P 的一条路上,则称P是G 的一个路径覆盖.P 中路径可以从V 的任何一个顶点开 ...

  5. BZOJ 2631 [国家集训队]Tree II (LCT)

    题目大意:给你一棵树,让你维护一个数据结构,支持 边的断,连 树链上所有点点权加上某个值 树链上所有点点权乘上某个值 求树链所有点点权和 (辣鸡bzoj又是土豪题,洛谷P1501传送门) LCT裸题, ...

  6. Poj1741/洛谷P4718 Tree(点分治)

    题面 有多组数据:Poj 无多组数据:洛谷 题解 点分治板子题,\(calc\)的时候搞一个\(two\ pointers\)扫一下统计答案就行了. #include <cmath> #i ...

  7. 洛谷P1198 [JSOI2008]最大数(单点修改,区间查询)

    洛谷P1198 [JSOI2008]最大数 简单的线段树单点问题. 问题:读入A和Q时,按照读入一个字符会MLE,换成读入字符串就可以了. #include<bits/stdc++.h> ...

  8. 洛谷.1501.[国家集训队]Tree II(LCT)

    题目链接 日常zz被define里没取模坑 //标记下放同线段树 注意51061^2 > 2147483647,要开unsigned int //*sz[]别忘了.. #include < ...

  9. 洛谷P1501 [国家集训队]Tree II(LCT)

    题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...

随机推荐

  1. Django的基本运用(垃圾分类)

    title: 利用Django实现一个能与用户交互的初级框架 author: Sun-Wind date: September 1, 2021 Django实现基本的框架 此框架的功能是搭建服务器,使 ...

  2. QT学习日记篇-02-QT信号和槽

    课程大纲: <1>给控件改名字 随着UI界面的控件变多,如果使用系统自带的名称,后期会让人不明觉厉,说白了,就是掌握C++的命名规则:易懂,条例清晰,人性化 方法:直接点击控件,进入右侧对 ...

  3. vue 微信二维码扫码登录,附加 自定义样式

    大概流程:   先安装 微信 的登录, 然后 局部引入,局部注册,方法调用,存 token,跳转路由 npm 安装 npm install vue-wxlogin --save-dev 微信安装 微信 ...

  4. vue 点击复制当前网址

    template 部分 <div  class="NewNoticeDetails-ctrlButton" @click="copy()">     ...

  5. Linux触摸驱动分析

    测试平台 宿主机平台:Ubuntu 12.04.4 LTS 目标机:Easy-ARM IMX283 目标机内核:Linux 2.6.35.3 触摸屏基础知识 一.结构 上图是电阻触摸屏的一个侧面剖视图 ...

  6. Linux内核中的Workqueue机制分析

    1. 什么是workqueue Linux中的workqueue(工作队列)主要是为了简化在内核创建线程而设计的.通过相应的工作队列接口,可以使开发人员只关心与特定功能相关的处理流程,而不必关心内核线 ...

  7. web、html概念快速入门

    1.C/S和B/S 总结,理论上如果硬件不考虑(带宽.(图像资源加载)显卡等),B/S可以完全替代C/S: 2.静态资源和动态资源 其中,访问时动态资源,服务器后台也会通过视图解析器转换成静态资源,因 ...

  8. go build 与go install

    相同点都能生成可执行文件 不同点go build 不能生成包文件, go install 可以生成包文件go build 生成可执行文件在当前目录下, go install 生成可执行文件在bin目录 ...

  9. vue-router路由钩子

    路由跳转前后,需要做某些操作,这时就可以使用路由钩子来监听路由的变化. 接收三个参数: to: Route: 即将要进入的目标路由对象 from: Route: 当前导航正要离开的路由 next: F ...

  10. 跨 Docker 宿主机 macvlan 类型

    跨 Docker 宿主机 macvlan 类型 前言 a. 本文主要为 Docker的视频教程 笔记. b. 环境为 三台 CentOS 7.0 虚拟机 (Vmware Workstation 15 ...