FZOJ 2176 easy problem ( 树链剖分 )

举报
Linux猿 发表于 2021/08/05 01:01:48 2021/08/05
【摘要】 题目链接~~> 做题感悟:感觉做多了树链剖分的题目,有许多是树链剖分 + 想法。。 解题思路:                 这题很明显的一点就是 k 很小,那就是告诉你可以从 k 入手,怎样入手呢 ? 观察可以发现无非最多是 k 类点 ,0 ~ k-1 ,分别表示与根的距离模 k...

题目链接~~>

做题感悟:感觉做多了树链剖分的题目,有许多是树链剖分 + 想法。。

解题思路:

                这题很明显的一点就是 k 很小,那就是告诉你可以从 k 入手,怎样入手呢 ? 观察可以发现无非最多是 k 类点 ,0 ~ k-1 ,分别表示与根的距离模 k .这样就可以把点分类加权值,但是每个线段树里存的还是所有元素,查询的时候对应查找。

代码:


  
  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 long long int
  20. #define L(x) (x * 2)
  21. #define R(x) (x * 2 + 1)
  22. const int INF = 0x3f3f3f3f ;
  23. const double esp = 0.00000000001 ;
  24. const double PI = acos(-1.0) ;
  25. const INT mod = 1234567891 ;
  26. const int MY = (1<<5) + 5 ;
  27. const int MX = 50000 + 5 ;
  28. const int S = 20 ;
  29. int n ,m ,k ,num ,idx ;
  30. int head[MX] ,top[MX] ,siz[MX] ,son[MX] ,dep[MX] ,ti[MX] ,to[MX] ,father[MX] ;
  31. struct Edge
  32. {
  33. int v ,next ;
  34. }E[MX*2] ;
  35. void addedge(int u ,int v)
  36. {
  37. E[num].v = v ; E[num].next = head[u] ;head[u] = num++ ;
  38. E[num].v = u ; E[num].next = head[v] ;head[v] = num++ ;
  39. }
  40. void dfs_find(int u ,int fa)
  41. {
  42. dep[u] = dep[fa] + 1 ;
  43. siz[u] = 1 ;
  44. son[u] = 0 ;
  45. father[u] = fa ;
  46. for(int i = head[u] ;i != -1 ;i = E[i].next)
  47. {
  48. int v = E[i].v ;
  49. if(v == fa) continue ;
  50. dfs_find(v ,u) ;
  51. siz[u] += siz[v] ;
  52. if(siz[son[u]] < siz[v]) son[u] = v ;
  53. }
  54. }
  55. void dfs_time(int u ,int fa)
  56. {
  57. top[u] = fa ;
  58. ti[u] = idx++ ;
  59. if(son[u]) dfs_time(son[u] ,top[u]) ;
  60. for(int i = head[u] ;i != -1 ;i = E[i].next)
  61. {
  62. int v = E[i].v ;
  63. if(v == son[u] || v == father[u]) continue ;
  64. dfs_time(v ,v) ;
  65. }
  66. to[u] = idx-1 ;
  67. }
  68. struct node
  69. {
  70. int le ,rt ,add ,c ;
  71. }T[6][MX*4] ;
  72. void push_down(int cnt ,int i)
  73. {
  74. int& temp = T[cnt][i].add ;
  75. if(temp)
  76. {
  77. T[cnt][L(i)].add += temp ;
  78. T[cnt][L(i)].c += temp ;
  79. T[cnt][R(i)].add += temp ;
  80. T[cnt][R(i)].c += temp ;
  81. temp = 0 ;
  82. }
  83. }
  84. void build(int cnt ,int i ,int le ,int rt)
  85. {
  86. T[cnt][i].le = le ; T[cnt][i].rt = rt ;
  87. T[cnt][i].add = T[cnt][i].c = 0 ;
  88. if(le == rt) return ;
  89. int Mid = (le + rt)>>1 ;
  90. build(cnt ,L(i) ,le ,Mid) ;
  91. build(cnt ,R(i) ,Mid+1 ,rt) ;
  92. }
  93. void section(int cnt ,int i ,int le ,int rt ,int val)
  94. {
  95. if(T[cnt][i].le == le && T[cnt][i].rt == rt)
  96. {
  97. T[cnt][i].add += val ;
  98. T[cnt][i].c += val ;
  99. return ;
  100. }
  101. push_down(cnt ,i) ;
  102. int Mid = (T[cnt][i].le + T[cnt][i].rt)>>1 ;
  103. if(le > Mid) section(cnt ,R(i) ,le ,rt ,val) ;
  104. else if(rt <= Mid) section(cnt ,L(i) ,le ,rt ,val) ;
  105. else
  106. {
  107. section(cnt ,L(i) ,le ,Mid ,val) ;
  108. section(cnt ,R(i) ,Mid+1 ,rt ,val) ;
  109. }
  110. }
  111. int Query(int cnt ,int i ,int pos)
  112. {
  113. if(T[cnt][i].le == T[cnt][i].rt)
  114. return T[cnt][i].c ;
  115. push_down(cnt ,i) ;
  116. int Mid = (T[cnt][i].le + T[cnt][i].rt)>>1 ;
  117. if(pos <= Mid) return Query(cnt ,L(i) ,pos) ; // 在左边
  118. else return Query(cnt ,R(i) ,pos) ;
  119. }
  120. int main()
  121. {
  122. //freopen("input.txt" ,"r" ,stdin) ;
  123. int Tx ,u ,v ,cnt ,x ,dt ,pos ,val ,cse = 1 ;
  124. scanf("%d" ,&Tx) ;
  125. while(Tx--)
  126. {
  127. scanf("%d%d%d" ,&n ,&m ,&k) ;
  128. num = 0 ;
  129. memset(head ,-1 ,sizeof(head)) ;
  130. for(int i = 1 ;i < n ; ++i)
  131. {
  132. scanf("%d%d" ,&u ,&v) ;
  133. addedge(u ,v) ;
  134. }
  135. dep[1] = siz[0] = 0 ;
  136. dfs_find(1 ,1) ;
  137. idx = 1 ;
  138. dfs_time(1 ,1) ;
  139. for(int i = 0 ;i < k ; ++i)
  140. build(i ,1 ,1 ,n) ;
  141. printf("Case#%d:\n" ,cse++) ;
  142. for(int i = 0 ;i < m ; ++i)
  143. {
  144. scanf("%d%d" ,&pos ,&x) ;
  145. if(pos == 1)
  146. {
  147. scanf("%d" ,&val) ;
  148. for(int j = 0 ;j < k ; ++j)
  149. {
  150. dt = (dep[x] - 1)%k ; // 根所在的集合
  151. cnt = (dt + j)%k ;
  152. section(cnt ,1 ,ti[x] ,to[x] ,(j+1)*val) ;
  153. }
  154. }
  155. else
  156. printf("%d\n" ,Query((dep[x]-1)%k ,1 ,ti[x])) ;
  157. }
  158. }
  159. return 0 ;
  160. }

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

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

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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