POJ 3237 Tree (树链剖分)

举报
Linux猿 发表于 2021/08/04 23:30:59 2021/08/04
【摘要】 题目链接~~> 做题感悟:只要会线段树区间更新再加上剖分就搞定了。 解题思路:                主要注意怎样区间更新就ok了 。树链剖分就是树上的线段树。 代码: #include<iostream>#include<sstream>#i...

题目链接~~>

做题感悟:只要会线段树区间更新再加上剖分就搞定了。

解题思路:

               主要注意怎样区间更新就ok了 。树链剖分就是树上的线段树。

代码:


  
  1. #include<iostream>
  2. #include<sstream>
  3. #include<map>
  4. #include<cmath>
  5. #include<fstream>
  6. #include<queue>
  7. #include<vector>
  8. #include<sstream>
  9. #include<cstring>
  10. #include<cstdio>
  11. #include<stack>
  12. #include<bitset>
  13. #include<ctime>
  14. #include<string>
  15. #include<cctype>
  16. #include<iomanip>
  17. #include<algorithm>
  18. using namespace std ;
  19. #define INT __int64
  20. #define L(x) (x * 2)
  21. #define R(x) (x * 2 + 1)
  22. const int INF = 0x3f3f3f3f ;
  23. const double esp = 0.0000000001 ;
  24. const double PI = acos(-1.0) ;
  25. const int mod = 1e9 + 7 ;
  26. const int MY = 1e7 + 5 ;
  27. const int MX = 10000 + 5 ;
  28. int n ,num ,idx ;
  29. int head[MX] ,dep[MX] ,top[MX] ,ti[MX] ,siz[MX] ,son[MX] ,father[MX] ;
  30. struct NODE
  31. {
  32. int u ,v ,w ;
  33. }e[MX] ;
  34. struct Edge
  35. {
  36. int v ,next ;
  37. }E[MX*2] ;
  38. void addedge(int u ,int v)
  39. {
  40. E[num].v = v ; E[num].next = head[u] ; head[u] = num++ ;
  41. E[num].v = u ; E[num].next = head[v] ; head[v] = num++ ;
  42. }
  43. void dfs_find(int u ,int fa)
  44. {
  45. dep[u] = dep[fa] + 1 ;
  46. siz[u] = 1 ;
  47. son[u] = 0 ;
  48. father[u] = fa ;
  49. for(int i = head[u] ;i != -1 ;i = E[i].next)
  50. {
  51. int v = E[i].v ;
  52. if(v == fa) continue ;
  53. dfs_find(v ,u) ;
  54. siz[u] += siz[v] ;
  55. if(siz[son[u]] < siz[v]) son[u] = v ;
  56. }
  57. }
  58. void dfs_time(int u ,int fa)
  59. {
  60. ti[u] = idx++ ;
  61. top[u] = fa ;
  62. if(son[u]) dfs_time(son[u] ,top[u]) ;
  63. for(int i = head[u] ;i != -1 ;i = E[i].next)
  64. {
  65. int v = E[i].v ;
  66. if(v == father[u] || v == son[u]) continue ;
  67. dfs_time(v ,v) ;
  68. }
  69. }
  70. struct node
  71. {
  72. int le ,rt ,Mi ,Mx ,add ;
  73. }T[MX*4] ;
  74. void build(int x ,int le ,int rt)
  75. {
  76. T[x].le = le ; T[x].rt = rt ;
  77. T[x].Mi = INF ; T[x].Mx = -INF ;
  78. T[x].add = 0 ;
  79. if(le == rt) return ;
  80. int Mid = (le + rt)>>1 ;
  81. build(L(x) ,le ,Mid) ;
  82. build(R(x) ,Mid+1 ,rt) ;
  83. }
  84. void push_down(int x)
  85. {
  86. if(T[x].le == T[x].rt) return ;
  87. if(T[x].add)
  88. {
  89. T[L(x)].Mi = -T[L(x)].Mi ;
  90. T[L(x)].Mx = -T[L(x)].Mx ;
  91. swap(T[L(x)].Mi ,T[L(x)].Mx) ;
  92. T[R(x)].Mi = -T[R(x)].Mi ;
  93. T[R(x)].Mx = -T[R(x)].Mx ;
  94. swap(T[R(x)].Mi ,T[R(x)].Mx) ;
  95. T[L(x)].add ^= 1 ;
  96. T[R(x)].add ^= 1 ;
  97. T[x].add = 0 ;
  98. }
  99. }
  100. void push_up(int x)
  101. {
  102. T[x].Mi = min(T[L(x)].Mi ,T[R(x)].Mi) ;
  103. T[x].Mx = max(T[L(x)].Mx ,T[R(x)].Mx) ;
  104. }
  105. void section(int x ,int le ,int rt) // 更新某个区间
  106. {
  107. if(T[x].le == le && T[x].rt == rt)
  108. {
  109. T[x].add ^= 1 ;
  110. T[x].Mi = -T[x].Mi ;
  111. T[x].Mx = -T[x].Mx ;
  112. swap(T[x].Mi ,T[x].Mx) ;
  113. return ;
  114. }
  115. if(T[x].le == T[x].rt) return ;
  116. push_down(x) ;
  117. int Mid = (T[x].le + T[x].rt)>>1 ;
  118. if(le > Mid)
  119. section(R(x) ,le ,rt) ;
  120. else if(rt <= Mid)
  121. section(L(x) ,le ,rt) ;
  122. else
  123. {
  124. section(L(x) ,le ,Mid) ;
  125. section(R(x) ,Mid+1 ,rt) ;
  126. }
  127. push_up(x) ;
  128. }
  129. void update(int x ,int pos ,int w)
  130. {
  131. if(T[x].le == T[x].rt)
  132. {
  133. T[x].Mi = w ;
  134. T[x].Mx = w ;
  135. T[x].add = 0 ;
  136. return ;
  137. }
  138. push_down(x) ;
  139. int Mid = (T[x].le + T[x].rt)>>1 ;
  140. if(pos <= Mid)
  141. update(L(x) ,pos ,w) ;
  142. else update(R(x) ,pos ,w) ;
  143. push_up(x) ;
  144. }
  145. int Query(int x ,int le ,int rt) // 询问某个区间
  146. {
  147. if(T[x].le == le && T[x].rt == rt)
  148. return T[x].Mx ;
  149. push_down(x) ;
  150. int Mid = (T[x].le + T[x].rt)>>1 ;
  151. if(le > Mid)
  152. return Query(R(x) ,le ,rt) ;
  153. else if(rt <= Mid)
  154. return Query(L(x) ,le ,rt) ;
  155. else
  156. return max(Query(L(x) ,le ,Mid) ,Query(R(x) ,Mid+1 ,rt)) ;
  157. push_up(x) ;
  158. }
  159. int LCA(int u ,int v)
  160. {
  161. if(u == v) return 0 ;
  162. int ans = -INF ;
  163. while(top[u] != top[v])
  164. {
  165. if(dep[top[u]] < dep[top[v]])
  166. swap(u ,v) ;
  167. ans = max(ans ,Query(1 ,ti[top[u]] ,ti[u])) ;
  168. u = father[top[u]] ;
  169. }
  170. if(dep[u] > dep[v])
  171. swap(u ,v) ;
  172. if(u != v)
  173. ans = max(ans ,Query(1 ,ti[u]+1 ,ti[v])) ;
  174. return ans ;
  175. }
  176. void change(int u ,int v)
  177. {
  178. while(top[u] != top[v])
  179. {
  180. if(dep[top[u]] < dep[top[v]])
  181. swap(u ,v) ;
  182. section(1 ,ti[top[u]] ,ti[u]) ;
  183. u = father[top[u]] ;
  184. }
  185. if(dep[u] > dep[v])
  186. swap(u ,v) ;
  187. section(1 ,ti[u]+1 ,ti[v]) ;
  188. }
  189. int main()
  190. {
  191. int Tx ;
  192. scanf("%d" ,&Tx) ;
  193. while(Tx--)
  194. {
  195. scanf("%d" ,&n) ;
  196. num = 0 ;
  197. memset(head ,-1 ,sizeof(head)) ;
  198. for(int i = 1 ;i < n ; ++i)
  199. {
  200. scanf("%d%d%d" ,&e[i].u ,&e[i].v ,&e[i].w) ;
  201. addedge(e[i].u ,e[i].v) ;
  202. }
  203. dep[1] = 0 ; siz[0] = 0 ;
  204. dfs_find(1 ,1) ;
  205. idx = 1 ;
  206. dfs_time(1 ,1) ;
  207. build(1 ,2 ,n) ;
  208. for(int i = 1 ;i < n ; ++i)
  209. {
  210. if(dep[e[i].u] < dep[e[i].v])
  211. swap(e[i].u ,e[i].v) ;
  212. update(1 ,ti[e[i].u] ,e[i].w) ;
  213. }
  214. int x ,y ;
  215. char s[10] ;
  216. while(true)
  217. {
  218. scanf("%s" ,s) ;
  219. if(s[0] == 'D') break ;
  220. scanf("%d%d" ,&x ,&y) ;
  221. if(s[0] == 'C')
  222. update(1 ,ti[e[x].u] ,y) ;
  223. else if(s[0] == 'N')
  224. change(x ,y) ;
  225. else if(s[0] == 'Q')
  226. cout<<LCA(x ,y)<<endl ;
  227. }
  228. }
  229. return 0 ;
  230. }



文章来源: blog.csdn.net,作者:Linux猿,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nyist_zxp/article/details/40116525

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。