记录编号 318112 评测结果 AAAAAAAAAA
题目名称 [HAOI 2015]树上操作 最终得分 100
用户昵称 Gravatar小e 是否通过 通过
代码语言 C++ 运行时间 1.229 s
提交时间 2016-10-08 21:03:20 内存使用 114.85 MiB
显示代码纯文本
  1. #include "stdio.h"
  2. #include "stdlib.h"
  3. typedef long long LL;
  4.  
  5. const int maxnumber = 1001000;
  6. struct Edge
  7. {
  8. int to, next;
  9. }edges[maxnumber << 1];
  10. int head[maxnumber], tot;
  11. int n, m;
  12. LL value[maxnumber], num;
  13. int depth[maxnumber], size[maxnumber], fa[maxnumber], son[maxnumber];
  14. int dfn[maxnumber], id[maxnumber], top[maxnumber], dfsclock;
  15. LL tree[maxnumber << 2], lazy[maxnumber << 2];
  16.  
  17. template <class T> inline void Read(T& a)
  18. {
  19. a = 0;
  20. int minus = 1;
  21. char ch = getchar();
  22. if(ch == '-') minus = -1;
  23. while(ch < '0' || ch > '9'){
  24. ch = getchar();
  25. if(ch == '-') minus = -1;
  26. }
  27. while(ch >= '0' && ch <= '9'){
  28. a = a * 10 + ch - '0';
  29. ch = getchar();
  30. }
  31. a = a * minus;
  32. }
  33.  
  34. template <class T> inline void Write(T a)
  35. {
  36. int cnt = 0;
  37. if(a < 0){
  38. putchar('-');
  39. a = -a;
  40. }
  41. char ch[50] = {'\0'};
  42. while(1){
  43. ch[++cnt] = a % 10 + '0';
  44. a /= 10;
  45. if(!a) break;
  46. }
  47. while(cnt)
  48. putchar(ch[cnt--]);
  49. puts("");
  50. }
  51.  
  52. template <class T> inline void Swap(T& a, T& b)
  53. {
  54. T tmp = a;
  55. a = b;
  56. b = tmp;
  57. }
  58.  
  59. inline void AddEdge(const int& from, const int& to)
  60. {
  61. edges[++tot].to = to;
  62. edges[tot].next = head[from];
  63. head[from] = tot;
  64. }
  65.  
  66. void Segment_Tree_Build(const int& l, const int& r, const int& rt)
  67. {
  68. // printf("l:%d r:%d rt:%d\n", l, r, rt); while(1);
  69. if(l == r){
  70. tree[rt] = value[id[l]];
  71. return;
  72. }
  73. const int mid = (l + r) >> 1, lch = rt << 1, rch = lch | 1;
  74. Segment_Tree_Build(l, mid, lch);
  75. Segment_Tree_Build(mid+1, r, rch);
  76. tree[rt] = tree[lch] + tree[rch];
  77. }
  78.  
  79. inline void PushDown(const int l, const int r, const int& rt)
  80. {
  81. const int mid = (l + r) >> 1,lch = rt << 1, rch = lch | 1;
  82. lazy[lch] += lazy[rt]; lazy[rch] += lazy[rt];
  83. tree[lch] += (LL)(mid - l + 1) * lazy[rt];
  84. tree[rch] += (LL)(r - mid) * lazy[rt];
  85. lazy[rt] = 0;
  86. }
  87.  
  88. void Segment_Tree_Add(const int& l, const int& r, const int& rt, const int& s, const int& t)
  89. {
  90. if(s <= l && t >= r){
  91. tree[rt] += (r - l + 1) * num;
  92. lazy[rt] += num;
  93. return;
  94. }
  95. if(lazy[rt]) PushDown(l, r, rt);
  96. const int mid = (l + r) >> 1, lch = rt << 1, rch = lch | 1;
  97. if(t <= mid) Segment_Tree_Add(l, mid, lch, s, t);
  98. else if(s >= mid + 1) Segment_Tree_Add(mid+1, r, rch, s, t);
  99. else{
  100. Segment_Tree_Add(l, mid, lch, s, mid);
  101. Segment_Tree_Add(mid+1, r, rch, mid+1, t);
  102. }
  103. tree[rt] = tree[lch] + tree[rch];
  104. }
  105.  
  106. LL Segment_Tree_Sum(const int& l, const int& r, const int& rt, const int& s, const int& t)
  107. {
  108. if(s <= l && t >= r) return tree[rt];
  109. if(lazy[rt]) PushDown(l, r, rt);
  110. const int mid = (l + r) >> 1, lch = rt << 1, rch = lch | 1;
  111. if(t <= mid) return Segment_Tree_Sum(l, mid, lch, s, t);
  112. else if(s >= mid + 1) return Segment_Tree_Sum(mid+1, r, rch, s, t);
  113. return Segment_Tree_Sum(l, mid, lch, s, mid) + Segment_Tree_Sum(mid+1, r, rch, mid+1, t);
  114. }
  115.  
  116. void DFS1(const int& a)
  117. {
  118. size[a] = 1;
  119. for(int i = head[a]; i; i = edges[i].next){
  120. int to = edges[i].to;
  121. if(to == fa[a]) continue;
  122. depth[to] = depth[a] + 1;
  123. fa[to] = a;
  124. DFS1(to);
  125. size[a] += size[to];
  126. if(size[to] > size[son[a]]) son[a] = to;
  127. }
  128. }
  129.  
  130. void DFS2(const int& a, const int& tp)
  131. {
  132. dfn[a] = ++dfsclock;
  133. id[dfsclock] = a;
  134. top[a] = tp;
  135. if(son[a]) DFS2(son[a], tp);
  136. for(int i = head[a]; i; i = edges[i].next){
  137. int to = edges[i].to;
  138. if(to == fa[a] || to == son[a]) continue;
  139. DFS2(to, to);
  140. }
  141. }
  142.  
  143. inline LL Query(int s, int t)
  144. {
  145. LL ret = 0;
  146. int f1 = top[s], f2 = top[t];
  147. while(f1 != f2){
  148. if(depth[f1] < depth[f2]){
  149. Swap(f1, f2);
  150. Swap(s, t);
  151. }
  152. ret += Segment_Tree_Sum(1, n, 1, dfn[f1], dfn[s]);
  153. s = fa[f1];
  154. f1 = top[s];
  155. }
  156. if(depth[s] < depth[t]) Swap(s, t);
  157. ret += Segment_Tree_Sum(1, n, 1, dfn[t], dfn[s]);
  158. return ret;
  159. }
  160.  
  161. #define SUBMIT
  162. int main(int argc, char const *argv[])
  163. {
  164. #ifdef SUBMIT
  165. freopen("haoi2015_t2.in", "r", stdin); freopen("haoi2015_t2.out", "w", stdout);
  166. #endif
  167.  
  168. int from, to, order, s;
  169. Read(n); Read(m);
  170. for(int i = 1; i <= n; i++) Read(value[i]);
  171. for(int i = 1; i < n; i++){
  172. Read(from); Read(to);
  173. AddEdge(from, to);
  174. AddEdge(to, from);
  175. }
  176.  
  177. depth[1] = 1;
  178. DFS1(1);
  179. DFS2(1, 1);
  180. Segment_Tree_Build(1, n, 1);
  181.  
  182. for(int i = 1; i <= m; i++){
  183. Read(order);
  184. if(order == 1){
  185. Read(s); Read(num);
  186. Segment_Tree_Add(1, n, 1, dfn[s], dfn[s]);
  187. }
  188. else if(order == 2){
  189. Read(s); Read(num);
  190. Segment_Tree_Add(1, n, 1, dfn[s], dfn[s] + size[s] - 1);
  191. }
  192. else{
  193. Read(s);
  194. Write(Query(s, 1));
  195. }
  196. }
  197.  
  198. #ifndef SUBMIT
  199. printf("\n----------\n");
  200. getchar(); getchar();
  201. #else
  202. fclose(stdin); fclose(stdout);
  203. #endif
  204.  
  205. return 0;
  206. }