ASTAR2016 ROUND2A 1003 Snacks

http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=701&pid=1003
http://acm.hdu.edu.cn/showproblem.php?pid=5692

Problem Description

百度科技园内有n个零食机,零食机之间通过n−1条路相互连通。每个零食机都有一个值v,表示为小度熊提供零食的价值。

由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化。小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次。另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机。

为小度熊规划一个路线,使得路线上的价值总和最大。

Input

输入数据第一行是一个整数T(T≤10),表示有T组测试数据。

对于每组数据,包含两个整数n,m(1≤n,m≤100000),表示有n个零食机,m次操作。

接下来n−1行,每行两个整数x和y(0≤x,y<n),表示编号为x的零食机与编号为y的零食机相连。

接下来一行由n个数组成,表示从编号为0到编号n−1的零食机的初始价值v(∣v∣<100000)。

接下来m行,有两种操作:0 x y,表示编号为x的零食机的价值变为y;1 x,表示询问从编号为0的零食机出发,必须经过编号为x零食机的路线中,价值总和的最大值。

本题可能栈溢出,辛苦同学们提交语言选择c++,并在代码的第一行加上:

#pragma comment(linker, "/STACK:1024000000,1024000000")

Output

对于每组数据,首先输出一行”Case #?:”,在问号处应填入当前数据的组数,组数从1开始计算。

对于每次询问,输出从编号为0的零食机出发,必须经过编号为x零食机的路线中,价值总和的最大值。

Sample Input

1
6 5
0 1
1 2
0 3
3 4
5 3
7 -5 100 20 -5 -7
1 1
1 3
0 2 -1
1 1
1 5

Sample Output

Case #1:
102
27
2
20

Solution

将树按照 dfs 序展开,那么询问 1 x 就是一段区间内的点,离 0 的距离的最大值。可以考虑区间最值查询的相关数据结构。

对于更改点权的操作,将其变成增加点权的操作,那么也就是带区间更新的区间最值查询,到此可以用线段树解决该题。

另外,可以一开始建立点权全部为 0 的树,然后更新添加点权,精简代码。

Code

  1. #pragma comment(linker, "/STACK:1024000000,1024000000") 
  2. #include <stdio.h> 
  3. #include <string.h> 
  4. #include <stdlib.h> 
  5.  
  6. #include <algorithm> 
  7. #include <vector> 
  8.  
  9. const int N = 100000 + 10
  10.  
  11. std::vector<std::vector<int> > g; 
  12.  
  13. int dfsl[N]; 
  14. int dfsr[N]; 
  15.  
  16. void dfs(int u, int f, int& timestamp) 

  17. dfsl[u] = ++timestamp; 
  18. for (int i = 0; i < (int) g[u].size(); ++i) { 
  19. int v = g[u][i]; 
  20. if (v == f) { 
  21. continue

  22. dfs(v, u, timestamp); 

  23. dfsr[u] = timestamp; 

  24.  
  25. struct segment_tree_t 

  26. #define ID ((l + r) | (l != r)) 
  27. #define IDL ((l + m) | (l != m)) 
  28. #define IDR ((m+1 + r) | (m+1 != r)) 
  29. #define LSON l, m 
  30. #define RSON m+1, r 
  31.  
  32. struct tree_node 

  33. long long maxlen; 
  34. long long flag; 
  35.  
  36. void add(long long x) 

  37. maxlen += x; 
  38. flag += x; 

  39. } tree[N << 1]; 
  40.  
  41. void build(int l, int r) 

  42. tree[ID].maxlen = tree[ID].flag = 0
  43. if (l == r) { 
  44. return

  45. int m = (l + r) >> 1
  46. build(LSON); build(RSON); 

  47.  
  48. void pushdown(int l, int r) 

  49. int m = (l + r) >> 1
  50. long long& flag = tree[ID].flag; 
  51. if (flag != 0) { 
  52. tree[IDL].add(flag); 
  53. tree[IDR].add(flag); 
  54. flag = 0


  55.  
  56. void pushup(int l, int r) 

  57. int m = (l + r) >> 1
  58. tree[ID].maxlen = std::max(tree[IDL].maxlen, tree[IDR].maxlen); 

  59.  
  60. void update(int l, int r, int x, int y, int add) 

  61. if (l == x && r == y) { 
  62. tree[ID].add(add); 
  63. return

  64.  
  65. int m = (l + r) >> 1
  66. pushdown(l, r); 
  67. if (y <= m) { 
  68. update(LSON, x, y, add); 

  69. else if (x > m) { 
  70. update(RSON, x, y, add); 

  71. else
  72. update(LSON, x, m, add); 
  73. update(RSON, m+1, y, add); 

  74. pushup(l, r); 

  75.  
  76. long long query(int l, int r, int x, int y) 

  77. if (l == x && r == y) { 
  78. return tree[ID].maxlen; 

  79.  
  80. int m = (l + r) >> 1
  81. pushdown(l, r); 
  82. if (y <= m) { 
  83. return query(LSON, x, y); 

  84. else if (x > m) { 
  85. return query(RSON, x, y); 

  86. else
  87. return std::max(query(LSON, x, m), query(RSON, m+1, y)); 


  88. } st; 
  89.  
  90. int a[N]; 
  91.  
  92. void task(int casi) 

  93. printf("Case #%d:\n", casi); 
  94.  
  95. int n, m; 
  96. scanf("%d %d", &n, &m); 
  97. g.clear(); 
  98. g.resize(n); 
  99. for (int i = 1; i < n; ++i) { 
  100. int u, v; 
  101. scanf("%d %d", &u, &v); 
  102. g[u].push_back(v); 
  103. g[v].push_back(u); 

  104.  
  105. int timestamp = 0
  106. dfs(0, -1, timestamp); 
  107.  
  108. st.build(1, n); 
  109. for (int i = 0; i < n; ++i) { 
  110. scanf("%d", a+i); 
  111. st.update(1, n, dfsl[i], dfsr[i], a[i]); 

  112. for (int mi = 1; mi <= m; ++mi) { 
  113. int cmd; 
  114. int x, y; 
  115. scanf("%d", &cmd); 
  116. if (cmd == 0) { 
  117. scanf("%d %d", &x, &y); 
  118. y -= a[x]; 
  119. st.update(1, n, dfsl[x], dfsr[x], y); 
  120. a[x] += y; 

  121. else
  122. scanf("%d", &x); 
  123. printf("%I64d\n", st.query(1, n, dfsl[x], dfsr[x])); 



  124.  
  125. int main() 

  126. int casc; 
  127. scanf("%d", &casc); 
  128. for (int casi = 1; casi <= casc; ++casi) { 
  129. task(casi); 

  130. return 0

转载于:https://www.cnblogs.com/gu-castle/p/5516366.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值