Description

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

Input

输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

Sample Input

4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4

Sample Output

4
1
2
2
10
6
5
6
5
16

HINT

 

Source

 树链剖分大裸题。
  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. using namespace std;
  5. #define maxn 30010
  6. #define root 1
  7. int n,next[*maxn],side[maxn],toit[*maxn],key[maxn],tot,son[maxn],father[maxn];
  8. int edge[maxn],pos[maxn],top[maxn],dep[maxn],heavy[maxn],ord[maxn];
  9. bool in[maxn];
  10. struct node
  11. {
  12. int l,r;
  13. int best,sum;
  14. int lc,rc;
  15. }seg[*maxn];
  16.  
  17. inline int big(int a,int b){if (a > b)return a;return b;}
  18. inline void add(int,int);
  19. inline void dfs(int,int);
  20. inline void link(int,int);
  21. inline void build(int,int);
  22. inline void change(int,int);
  23. inline void find_best(int,int);
  24. inline void find_sum(int,int);
  25. inline int seg_sum(int,int,int);
  26. inline int seg_best(int,int,int);
  27.  
  28. int main()
  29. {
  30. freopen("1036.in","r",stdin);
  31. freopen("1036.out","w",stdout);
  32. scanf("%d",&n);
  33. int i,a,b;
  34. for (i = ;i<n;i++)
  35. {
  36. scanf("%d %d",&a,&b);
  37. add(a,b); add(b,a);
  38. }
  39. for (i = ;i<=n;i++)
  40. scanf("%d",key+i);
  41. tot = ;
  42. dfs(root,);
  43. tot = ;
  44. memset(in,,sizeof(in));
  45. link(root,root);
  46. tot = ;
  47. build(,n);
  48. int T;
  49. scanf("%d\n",&T);
  50. char sign[];
  51. while (T)
  52. {
  53. T--;
  54. scanf("%s %d %d\n",sign,&a,&b);
  55. if (sign[] == 'Q')
  56. {
  57. if (sign[] == 'M')
  58. find_best(a,b);
  59. if (sign[] == 'S')
  60. find_sum(a,b);
  61. }
  62. else
  63. key[a] = b,change(a,);
  64.  
  65. }
  66. return ;
  67. }
  68.  
  69. inline void add(int a,int b)
  70. {
  71. tot++;
  72. toit[tot] = b;
  73. next[tot] = side[a];
  74. side[a] = tot;
  75. }
  76.  
  77. inline void dfs(int a,int deep)
  78. {
  79. in[a] = true; dep[a] = deep;
  80. int u = side[a],v;
  81. son[a] = ;
  82. while (u != )
  83. {
  84. v = toit[u];
  85. if (!in[v])
  86. {
  87. father[v] = a;
  88. edge[++tot] = v;
  89. dfs(v,deep+);
  90. if (son[heavy[a]] < son[v])
  91. heavy[a] = v;
  92. son[a] += son[v];
  93. }
  94. u = next[u];
  95. }
  96. }
  97.  
  98. inline void link(int a,int high)
  99. {
  100. top[a] = high;
  101. pos[a] = ++tot;
  102. ord[tot] = a;
  103. in[a] = true;
  104. if (heavy[a] != )
  105. link(heavy[a],high);
  106. else return;
  107. int u = side[a],v;
  108. while (u != )
  109. {
  110. v = toit[u];
  111. if (!in[v])
  112. link(v,v);
  113. u = next[u];
  114. }
  115. }
  116.  
  117. inline void build(int l,int r)
  118. {
  119. seg[tot].l = l;
  120. seg[tot].r = r;
  121. if (l == r)
  122. {
  123. seg[tot].best = key[ord[l]];
  124. seg[tot].sum = key[ord[l]];
  125. return;
  126. }
  127. int mid = ((l+r)>>);
  128. int k = tot;
  129. seg[k].lc = ++tot;
  130. build(l,mid);
  131. seg[k].rc = ++tot;
  132. build(mid+,r);
  133. seg[k].best = big(seg[seg[k].lc].best,seg[seg[k].rc].best);
  134. seg[k].sum = seg[seg[k].lc].sum+seg[seg[k].rc].sum;
  135. }
  136.  
  137. inline void change(int a,int now)
  138. {
  139. if (seg[now].l == seg[now].r)
  140. {
  141. seg[now].best = key[a];
  142. seg[now].sum = key[a];
  143. return;
  144. }
  145. if (seg[seg[now].lc].l<=pos[a]&&seg[seg[now].lc].r>=pos[a])
  146. change(a,seg[now].lc);
  147. else change(a,seg[now].rc);
  148. seg[now].best = big(seg[seg[now].lc].best,seg[seg[now].rc].best);
  149. seg[now].sum = seg[seg[now].lc].sum + seg[seg[now].rc].sum;
  150. }
  151.  
  152. inline void find_sum(int a,int b)
  153. {
  154. int sum = ;
  155. while (top[a] != top[b])
  156. {
  157. if (dep[top[a]] >= dep[top[b]])
  158. {
  159. sum += seg_sum(pos[top[a]],pos[a],);
  160. a = father[top[a]];
  161. }
  162. else
  163. {
  164. sum += seg_sum(pos[top[b]],pos[b],);
  165. b = father[top[b]];
  166. }
  167. }
  168. if (pos[a] <= pos[b])
  169. sum += seg_sum(pos[a],pos[b],);
  170. else
  171. sum += seg_sum(pos[b],pos[a],);
  172. printf("%d\n",sum);
  173. }
  174.  
  175. inline void find_best(int a,int b)
  176. {
  177. int best = -;
  178. while (top[a] != top[b])
  179. {
  180. if (dep[top[a]] >= dep[top[b]])
  181. {
  182. best = big(best,seg_best(pos[top[a]],pos[a],));
  183. a = father[top[a]];
  184. }
  185. else
  186. {
  187. best = big(best,seg_best(pos[top[b]],pos[b],));
  188. b = father[top[b]];
  189. }
  190. }
  191. if (pos[a] <= pos[b])
  192. best = big(best,seg_best(pos[a],pos[b],));
  193. else
  194. best = big(best,seg_best(pos[b],pos[a],));
  195. printf("%d\n",best);
  196. }
  197.  
  198. inline int seg_best(int l,int r,int now)
  199. {
  200. if (seg[now].l >=l && seg[now].r <=r)
  201. return seg[now].best;
  202. int ret =-;
  203. int t;
  204. t = seg[now].lc;
  205. if (seg[t].l<=l&&seg[t].r>=l)
  206. ret = big(ret,seg_best(l,r,t));
  207. else if (seg[t].l>=l&&seg[t].l<=r)
  208. ret = big(ret,seg_best(l,r,t));
  209. else if (seg[t].r>=l&&seg[t].r<=r)
  210. ret = big(ret,seg_best(l,r,t));
  211. t = seg[now].rc;
  212. if (seg[t].l<=l&&seg[t].r>=l)
  213. ret = big(ret,seg_best(l,r,t));
  214. else if (seg[t].l>=l&&seg[t].l<=r)
  215. ret = big(ret,seg_best(l,r,t));
  216. else if (seg[t].r>=l&&seg[t].r<=r)
  217. ret = big(ret,seg_best(l,r,t));
  218. return ret;
  219. }
  220.  
  221. inline int seg_sum(int l,int r,int now)
  222. {
  223. if (seg[now].l >=l && seg[now].r <=r)
  224. return seg[now].sum;
  225. int ret = ;
  226. int t;
  227. t = seg[now].lc;
  228. if (seg[t].l<=l&&seg[t].r>=l)
  229. ret += seg_sum(l,r,t);
  230. else if (seg[t].l>=l&&seg[t].l<=r)
  231. ret += seg_sum(l,r,t);
  232. else if (seg[t].r>=l&&seg[t].r<=r)
  233. ret += seg_sum(l,r,t);
  234. t = seg[now].rc;
  235. if (seg[t].l<=l&&seg[t].r>=l)
  236. ret += seg_sum(l,r,t);
  237. else if (seg[t].l>=l&&seg[t].l<=r)
  238. ret += seg_sum(l,r,t);
  239. else if (seg[t].r>=l&&seg[t].r<=r)
  240. ret += seg_sum(l,r,t);
  241. return ret;
  242. }

BZOJ 1036 树的统计的更多相关文章

  1. BZOJ 1036 树的统计-树链剖分

    [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12904 Solved: 5191[Submit][Status ...

  2. Codevs 2460 == BZOJ 1036 树的统计

     2460 树的统计 2008年省队选拔赛浙江 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 一棵树上有n个节点,编号分别为1 ...

  3. BZOJ 1036 树的统计Count 树链剖分模板题

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1036 题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将 ...

  4. [置顶] bzoj 1036 树的统计Count 点权值模板

    树链剖分 点权型可做模板,链路剖分的思想把点hash到线段树的上,然后可通过n*(log(n)*log(n))的复杂度在树上操作,在线段树上能操作的在链路上都能操作. #include<cstd ...

  5. BZOJ 1036 树的统计(树链剖分)

    点权树链剖分模板题. # include <cstdio> # include <cstring> # include <cstdlib> # include &l ...

  6. bzoj 1036 树的统计Count

    题目大意: 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w 我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u ...

  7. BZOJ - 1036 树的统计Count (LCT)

    LCT试炼题(代码量居然完爆树剖?) #include<bits/stdc++.h> using namespace std; ,inf=0x3f3f3f3f; ],flp[N],n,m, ...

  8. Bzoj 1036 树的统计 分类: ACM TYPE 2014-12-29 18:55 72人阅读 评论(0) 收藏

    Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. Q ...

  9. BZOJ 1036 树的统计 | 树链剖分模板题

    又做了一遍--去掉读入优化只有八十行~ #include <cstdio> #include <cstring> #include <algorithm> usin ...

随机推荐

  1. EnterpriseArchitectect 软件的勾选的几个选项对应的中文意思

    Business Process 业务流程 Requirements 需求分析 Use Case 用例 Domain Model 领域模型 Class 类 Database 数据库设计 Compone ...

  2. Linux下对后台进程通过kill传递信号不起作用的问题

    在阅读APUE信号一章时,我遇到Linux下对后台进程通过kill传递信号不起作用的问题 具体情形与如下链接中的老兄一致: http://bbs.csdn.net/topics/390335913?p ...

  3. 如何将ER图转换成关系模式集

    在ER图中,主要是实体类型和联系类型. 1.实体类型的转换 (“——”表示对应关系) 实体类型——关系模式 实体的属性——关系模式的属性 实体标识符——关系模式的键 2.联系的转换 一元联系较简单,三 ...

  4. Android无法更新sdk的解决办法

    修改 windows/system32/drivers/etc/hosts 文件 添加 203.208.46.146 dl.google.com203.208.46.146 dl-ssl.google ...

  5. 怎样创建TWaver 3D的轮廓选中效果

    在一般的游戏中.物体的选中效果会是这样: TWaver 3D中,物体的默认的选中效果一般都是一个方方正正的外框.在HTML5的Mono版本号中,TWaver提供了轮廓线样式的选中效果. 通过例如以下代 ...

  6. UVA 10627 - Infinite Race(数论)

    UVA 10627 - Infinite Race option=com_onlinejudge&Itemid=8&page=show_problem&category=516 ...

  7. Activity间的跳转,startActivity与startActivityForResult

    JreduCh04 2016-07-30跳转 (由一个画面跳转到另一个画面)两种方法:Intent中 startActivity.startActivityForResult.后者可设置request ...

  8. copssh加bitvise

    只是简单记录下自己在成功使用的方案: 目的:为了突破公司对网站和qq的限制 具备的条件:一台云服务器.Copssh_4.1.0.bitvise ssh client 4.62.公司电脑客户端 一.首先 ...

  9. iOS英文 汉化,如调用相册,相机改“cancel”,“photos”为“取消”,“相机”

    调用系统相册.相机发现是英文的系统相簿界面后标题显示“photos”,但是手机语言已经设置显示中文,纠结半天,最终在info.plist设置解决问题. 只需要改三个地方: 1.plist文件中: 2. ...

  10. HTML页面中启用360浏览器极速模式

    今天做页面突然遇到浏览器一直在兼容模式下运行,体验不好,通过查询文档,在<head>中加入<meta name="renderer" content=" ...