经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
月下“毛景树”(边权树链剖分)
来源:cnblogs  作者:Fighting_sh  时间:2018/9/25 19:12:34  对本文有异议

月下“毛景树”

https://www.luogu.org/problemnew/show/P4315

题目描述

毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。

爬啊爬~爬啊爬毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:

  • Change k w:将第k条树枝上毛毛果的个数改变为w个。

  • Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。

  • Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:

  • Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。

输入输出格式

输入格式:

第一行一个正整数N。

接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。

 

输出格式:

对于毛毛虫的每个询问操作,输出一个答案。

 

输入输出样例

输入样例#1: 
  1. 4
  2. 1 2 8
  3. 1 3 7
  4. 3 4 9
  5. Max 2 4
  6. Cover 2 4 5
  7. Add 1 4 10
  8. Change 1 16
  9. Max 2 4
  10. Stop
输出样例#1: 
  1. 9
  2. 16

说明

1<=N<=100,000,操作+询问数目不超过100,000。

保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。

 

裸的树链剖分,要注意的点就是覆盖的优先级比加法的大,重点就是pushdown函数

  1. 1 #include<iostream>
  2. 2 #include<cstring>
  3. 3 #include<string>
  4. 4 #include<cmath>
  5. 5 #include<cstdio>
  6. 6 #include<algorithm>
  7. 7 #include<vector>
  8. 8 #define maxn 100005
  9. 9 #define lson l,mid,rt<<1
  10. 10 #define rson mid+1,r,rt<<1|1
  11. 11 using namespace std;
  12. 12
  13. 13 int tree[maxn<<3],Add[maxn<<3],Change[maxn<<3];
  14. 14 int n;
  15. 15 int v[maxn],val[maxn];
  16. 16 int dep[maxn],fa[maxn],siz[maxn],son[maxn],id[maxn],top[maxn],cnt;
  17. 17 vector<int>ve[maxn];
  18. 18 struct sair{
  19. 19 int x,y,len;
  20. 20 }p[maxn];
  21. 21
  22. 22 void pushup(int rt){
  23. 23 tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
  24. 24 }
  25. 25
  26. 26 void pushdown(int rt){
  27. 27 if(Change[rt]!=-1){
  28. 28 Change[rt<<1]=Change[rt<<1|1]=Change[rt];
  29. 29 Add[rt<<1]=Add[rt<<1|1]=0;
  30. 30 tree[rt<<1]=tree[rt<<1|1]=Change[rt];
  31. 31 }
  32. 32 if(Add[rt]){
  33. 33 Add[rt<<1]+=Add[rt];
  34. 34 Add[rt<<1|1]+=Add[rt];
  35. 35 tree[rt<<1]+=Add[rt];
  36. 36 tree[rt<<1|1]+=Add[rt];
  37. 37 }
  38. 38 Change[rt]=-1;
  39. 39 Add[rt]=0;
  40. 40 }
  41. 41
  42. 42 void build(int l,int r,int rt){
  43. 43 Add[rt]=0;
  44. 44 Change[rt]=-1;
  45. 45 if(l==r){
  46. 46 tree[rt]=val[l];
  47. 47 return;
  48. 48 }
  49. 49 int mid=(l+r)/2;
  50. 50 build(lson);
  51. 51 build(rson);
  52. 52 pushup(rt);
  53. 53 }
  54. 54
  55. 55 void add(int L,int R,int k,int l,int r,int rt){
  56. 56 if(L<=l&&R>=r){
  57. 57 tree[rt]+=k;
  58. 58 Add[rt]+=k;
  59. 59 pushdown(rt);
  60. 60 return;
  61. 61 }
  62. 62 int mid=(l+r)/2;
  63. 63 pushdown(rt);
  64. 64 if(L<=mid) add(L,R,k,lson);
  65. 65 if(R>mid) add(L,R,k,rson);
  66. 66 pushup(rt);
  67. 67 }
  68. 68
  69. 69 void change(int L,int R,int k,int l,int r,int rt){
  70. 70 if(L<=l&&R>=r){
  71. 71 tree[rt]=k;
  72. 72 Add[rt]=0;
  73. 73 Change[rt]=k;
  74. 74 pushdown(rt);
  75. 75 return;
  76. 76 }
  77. 77 int mid=(l+r)/2;
  78. 78 pushdown(rt);
  79. 79 if(L<=mid) change(L,R,k,lson);
  80. 80 if(R>mid) change(L,R,k,rson);
  81. 81 pushup(rt);
  82. 82 }
  83. 83
  84. 84 int query(int L,int R,int l,int r,int rt){
  85. 85 if(L<=l&&R>=r){
  86. 86 return tree[rt];
  87. 87 }
  88. 88 int mid=(l+r)/2;
  89. 89 pushdown(rt);
  90. 90 int ans=0;
  91. 91 if(L<=mid) ans=max(ans,query(L,R,lson));
  92. 92 if(R>mid) ans=max(ans,query(L,R,rson));
  93. 93 pushup(rt);
  94. 94 return ans;
  95. 95 }
  96. 96
  97. 97 void dfs1(int now,int f,int deep){
  98. 98 dep[now]=deep;
  99. 99 siz[now]=1;
  100. 100 fa[now]=f;
  101. 101 int maxson=-1;
  102. 102 for(int i=0;i<ve[now].size();i++){
  103. 103 if(ve[now][i]==f) continue;
  104. 104 dfs1(ve[now][i],now,deep+1);
  105. 105 siz[now]+=siz[ve[now][i]];
  106. 106 if(siz[ve[now][i]]>maxson){
  107. 107 maxson=siz[ve[now][i]];
  108. 108 son[now]=ve[now][i];
  109. 109 }
  110. 110 }
  111. 111 }
  112. 112
  113. 113 void dfs2(int now,int topp){
  114. 114 id[now]=++cnt;
  115. 115 val[cnt]=v[now];
  116. 116 top[now]=topp;
  117. 117 if(!son[now]) return;
  118. 118 dfs2(son[now],topp);
  119. 119 for(int i=0;i<ve[now].size();i++){
  120. 120 if(ve[now][i]==son[now]||ve[now][i]==fa[now]) continue;
  121. 121 dfs2(ve[now][i],ve[now][i]);
  122. 122 }
  123. 123 }
  124. 124
  125. 125 int qRange(int x,int y){
  126. 126 int t1 = top[x], t2 = top[y];
  127. 127 int res = 0;
  128. 128 while(t1 != t2) {
  129. 129 if(dep[t1] < dep[t2]) {
  130. 130 swap(t1, t2); swap(x, y);
  131. 131 }
  132. 132 res = max(res,query(id[t1], id[x], 1, n, 1));
  133. 133 x = fa[t1]; t1 = top[x];
  134. 134 }
  135. 135 if(x == y) return res;
  136. 136 if(dep[x] > dep[y]) swap(x, y);
  137. 137 return max(res,query(id[son[x]], id[y], 1, n, 1));
  138. 138 }
  139. 139
  140. 140 void addRange(int x,int y,int k){
  141. 141 int t1 = top[x], t2 = top[y];
  142. 142 while(t1 != t2) {
  143. 143 if(dep[t1] < dep[t2]) {
  144. 144 swap(t1, t2); swap(x, y);
  145. 145 }
  146. 146 add(id[t1], id[x], k, 1, n, 1);
  147. 147 x = fa[t1]; t1 = top[x];
  148. 148 }
  149. 149 if(x == y) return ;
  150. 150 if(dep[x] > dep[y]) swap(x, y);
  151. 151 add(id[son[x]], id[y], k, 1, n, 1);
  152. 152 }
  153. 153
  154. 154 void changeRange(int x,int y,int k){
  155. 155 int t1 = top[x], t2 = top[y];
  156. 156 while(t1 != t2) {
  157. 157 if(dep[t1] < dep[t2]) {
  158. 158 swap(t1, t2); swap(x, y);
  159. 159 }
  160. 160 change(id[t1], id[x], k, 1, n, 1);
  161. 161 x = fa[t1]; t1 = top[x];
  162. 162 }
  163. 163 if(x == y) return ;
  164. 164 if(dep[x] > dep[y]) swap(x, y);
  165. 165 change(id[son[x]], id[y], k, 1, n, 1);
  166. 166 }
  167. 167
  168. 168 int main(){
  169. 169 std::ios::sync_with_stdio(false);
  170. 170 int m,r;
  171. 171 cin>>n;
  172. 172 for(int i=1;i<n;i++){
  173. 173 cin>>p[i].x>>p[i].y>>p[i].len;
  174. 174 ve[p[i].x].push_back(p[i].y);
  175. 175 ve[p[i].y].push_back(p[i].x);
  176. 176 }
  177. 177 int z,x,y;
  178. 178 string pos;
  179. 179 cnt=0;
  180. 180 dfs1(1,0,1);
  181. 181 dfs2(1,1);
  182. 182 build(1,n,1);
  183. 183 int xx;
  184. 184 for(int i=1;i<n;i++){
  185. 185 if(dep[p[i].x]<dep[p[i].y]) xx=p[i].y;
  186. 186 else xx=p[i].x;
  187. 187 change(id[xx],id[xx],p[i].len,1,n,1);
  188. 188 }
  189. 189 while(cin>>pos){
  190. 190 if(pos=="Stop") break;
  191. 191 cin>>x>>y;
  192. 192 if(pos=="Max"){
  193. 193 cout<<qRange(x,y)<<endl;
  194. 194 }
  195. 195 else if(pos=="Cover"){
  196. 196 cin>>z;
  197. 197 changeRange(x,y,z);
  198. 198 }
  199. 199 else if(pos=="Add"){
  200. 200 cin>>z;
  201. 201 addRange(x,y,z);
  202. 202 }
  203. 203 else if(pos=="Change"){
  204. 204 if(dep[p[x].x]<dep[p[x].y]) xx=p[x].y;
  205. 205 else xx=p[x].x;
  206. 206 change(id[xx],id[xx],y,1,n,1);
  207. 207 p[x].len=y;
  208. 208 }
  209. 209 }
  210. 210 }
  211. 211 /*
  212. 212 7
  213. 213 1 2 1
  214. 214 1 3 2
  215. 215 2 4 3
  216. 216 2 5 4
  217. 217 3 7 6
  218. 218 5 6 5
  219. 219 Max 1 6
  220. 220 */
View Code

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号