题目描述

一棵树上有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本身

输入输出格式

输入格式:

输入文件的第一行为一个整数n,表示节点的个数。

接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。

接下来一行n个整数,第i个整数wi表示节点i的权值。

接下来1行,为一个整数q,表示操作的总数。

接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。

输出格式:

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

输入输出样例

输入样例#1:
复制

  1. 4
  2. 1 2
  3. 2 3
  4. 4 1
  5. 4 2 1 3
  6. 12
  7. QMAX 3 4
  8. QMAX 3 3
  9. QMAX 3 2
  10. QMAX 2 3
  11. QSUM 3 4
  12. QSUM 2 1
  13. CHANGE 1 5
  14. QMAX 3 4
  15. CHANGE 3 6
  16. QMAX 3 4
  17. QMAX 2 4
  18. QSUM 3 4
输出样例#1: 复制

  1. 4
  2. 1
  3. 2
  4. 2
  5. 10
  6. 6
  7. 5
  8. 6
  9. 5
  10. 16

说明

对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

题解

先剖一下。

CHANGE:把dfn[x]处改为t

然后线段树同时维护两个值:mac(区间内最大值)和sum(区间和)

在修改的时候,先递归到叶子节点,然后在回溯的同时维护mac和sum,单次复杂度logn。

就星了。

  1. /*
  2. qwerta
  3. P2590 [ZJOI2008]树的统计
  4. Accepted
  5. 100
  6. 代码 C++,3.62KB
  7. 提交时间 2018-09-11 19:18:59
  8. 耗时/内存
  9. 3536ms, 6424KB
  10. */
  11. #include<cmath>
  12. #include<cstdio>
  13. #include<iostream>
  14. #include<algorithm>
  15. using namespace std;
  16. #define R register
  17. #define LL long long
  18. inline int read()
  19. {
  20. char ch=getchar();
  21. int x=;bool s=;
  22. while(ch<''||ch>''){if(ch=='-')s=;ch=getchar();}
  23. while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
  24. return s?x:-x;
  25. }
  26. const int MAXN=+;
  27. struct emm{
  28. int e,f;
  29. }b[*MAXN];
  30. int h[MAXN];
  31. int tot=;
  32. void con(int x,int y)
  33. {
  34. b[++tot].f=h[x];
  35. h[x]=tot;
  36. b[tot].e=y;
  37. b[++tot].f=h[y];
  38. h[y]=tot;
  39. b[tot].e=x;
  40. return;
  41. }
  42. int s;
  43. int d[MAXN],fa[MAXN],top[MAXN],siz[MAXN],z[MAXN];
  44. void dfs(int x)
  45. {
  46. siz[x]=,top[x]=x;
  47. int mac=,macc=-;
  48. for(int i=h[x];i;i=b[i].f)
  49. if(!d[b[i].e])
  50. {
  51. d[b[i].e]=d[x]+;
  52. fa[b[i].e]=x;
  53. dfs(b[i].e);
  54. siz[x]+=siz[b[i].e];
  55. if(macc<siz[b[i].e]){mac=b[i].e,macc=siz[b[i].e];}
  56. }
  57. z[x]=mac;
  58. top[mac]=x;
  59. return;
  60. }
  61. int q[MAXN],dfn[MAXN];
  62. void dfss(int x)
  63. {
  64. q[++tot]=x;
  65. dfn[x]=tot;
  66. if(z[x])dfss(z[x]);
  67. for(int i=h[x];i;i=b[i].f)
  68. if(fa[b[i].e]==x&&b[i].e!=z[x])
  69. dfss(b[i].e);
  70. return;
  71. }
  72. int fitop(int x)
  73. {
  74. if(top[x]==x)return x;
  75. return top[x]=fitop(top[x]);
  76. }
  77. int val[MAXN];
  78. struct ahh{
  79. int l,r,mid,mac;
  80. long long sum;
  81. }a[*MAXN];
  82. #define lz (i<<1)
  83. #define rz ((i<<1)|1)
  84. #define md a[i].mid
  85. void build(int i,int ll,int rr)
  86. {
  87. a[i].l=ll;
  88. a[i].r=rr;
  89. if(ll==rr){a[i].mac=a[i].sum=val[q[ll]];return;}
  90. md=(ll+rr)>>;
  91. build(lz,ll,md);
  92. build(rz,md+,rr);
  93. a[i].mac=max(a[lz].mac,a[rz].mac);
  94. a[i].sum=a[lz].sum+a[rz].sum;
  95. return;
  96. }
  97. void change(int i,int x,int k)
  98. {
  99. if(a[i].l==a[i].r){a[i].mac=a[i].sum=k;return;}
  100. if(x<=md)change(lz,x,k);
  101. else change(rz,x,k);
  102. a[i].mac=max(a[lz].mac,a[rz].mac);
  103. a[i].sum=a[lz].sum+a[rz].sum;
  104. return;
  105. }
  106. long long ans;
  107. void findmac(int i,int ll,int rr)
  108. {
  109. if(a[i].l==ll&&a[i].r==rr){if(a[i].mac>ans)ans=a[i].mac;return;}
  110. if(rr<=md)findmac(lz,ll,rr);
  111. else if(md+<=ll)findmac(rz,ll,rr);
  112. else {findmac(lz,ll,md);findmac(rz,md+,rr);}
  113. return;
  114. }
  115. void findsum(int i,int ll,int rr)
  116. {
  117. if(a[i].l==ll&&a[i].r==rr){ans+=a[i].sum;return;}
  118. if(rr<=md)findsum(lz,ll,rr);
  119. else if(md+<=ll)findsum(rz,ll,rr);
  120. else {findsum(lz,ll,md);findsum(rz,md+,rr);}
  121. return;
  122. }
  123. int main()
  124. {
  125. //freopen("a.in","r",stdin);
  126. int n;
  127. cin>>n;
  128. for(int i=;i<n;++i)
  129. {
  130. int u,v;
  131. cin>>u>>v;
  132. con(u,v);
  133. }
  134. s=min(,n);
  135. d[s]=;
  136. dfs(s);
  137. tot=;
  138. dfss(s);
  139. for(int i=;i<=n;++i)
  140. top[i]=fitop(i);
  141. for(int i=;i<=n;++i)
  142. cin>>val[i];
  143. build(,,n);
  144. int q;
  145. cin>>q;
  146. for(int i=;i<=q;++i)
  147. {
  148. string st;
  149. cin>>st;
  150. if(st[]=='C')
  151. {
  152. int u,t;
  153. cin>>u>>t;
  154. change(,dfn[u],t);
  155. }
  156. else if(st[]=='M')
  157. {
  158. int u,v;
  159. cin>>u>>v;
  160. ans=-;
  161. while(top[u]!=top[v])
  162. {
  163. if(d[top[u]]<d[top[v]])swap(u,v);
  164. findmac(,dfn[top[u]],dfn[u]);
  165. u=fa[top[u]];
  166. }
  167. if(d[u]<d[v])swap(u,v);
  168. findmac(,dfn[v],dfn[u]);
  169. cout<<ans<<endl;
  170. }
  171. else
  172. {
  173. int u,v;
  174. cin>>u>>v;
  175. ans=;
  176. while(top[u]!=top[v])
  177. {
  178. if(d[top[u]]<d[top[v]])swap(u,v);
  179. findsum(,dfn[top[u]],dfn[u]);
  180. u=fa[top[u]];
  181. }
  182. if(d[u]<d[v])swap(u,v);
  183. findsum(,dfn[v],dfn[u]);
  184. cout<<ans<<endl;
  185. }
  186. }
  187. return ;
  188. }

「ZJOI2008」「LuoguP2590」树的统计(树链剖分的更多相关文章

  1. BZOJ 1036: [ZJOI2008]树的统计Count-树链剖分(点权)(单点更新、路径节点最值、路径求和)模板,超级认真写了注释啊啊啊

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 23015  Solved: 9336[Submit ...

  2. 树的统计Count---树链剖分

    NEFU专项训练十和十一——树链剖分 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t ...

  3. luoguP2590 [ZJOI2008]树的统计(树链剖分)

    luogu P2590 [ZJOI2008]树的统计 题目 #include<iostream> #include<cstdlib> #include<cstdio> ...

  4. BZOJ1036[ZJOI2008]树的统计——树链剖分+线段树

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

  5. 洛谷P2590 [ZJOI2008] 树的统计 [树链剖分]

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

  6. [ZJOI2008]树的统计——树链剖分

    本题是一个树链剖分裸题,由于比较菜,老是RE,后来发现是因为使用了全局变量. /************************************************************ ...

  7. [luogu P2590 ZJOI2008] 树的统计 (树链剖分)

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

  8. BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)

    潇爷昨天刚刚讲完...感觉得还可以...对着模板打了个模板...还是不喜欢用指针.... 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Lim ...

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

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

  10. [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分

    题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...

随机推荐

  1. java使用jxl,自动导出数据excle,quartz自动发送邮件

    =============JAVA后台代码===================== package com.qgc.service.autoSendMsg.AutoSendMsg import ja ...

  2. Google解决跨域

    1.添加   --disable-web-security --user-data-dir=D:\tmp 2.在D的根目录新建tmp文件夹

  3. TCP No-Delay

    Nagle 算法 由于TCP中包头的大小是固定的,所以在数据(Payload)大小很小的时候IP报文的有效传输率是很低的,Nagle算法就是将多个即将发送的小段的用户数据,缓存并合并成一个大段数据时, ...

  4. HUD 1506 Largest Rectangle in a Histogram

    Largest Rectangle in a Histogram Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 ...

  5. Spring MVC集成Spring Data Reids和Spring Session实现Session共享出现:No bean named 'springSessionRepositoryFilter' available

    出现这个问题:No bean named 'springSessionRepositoryFilter' available的的原因: 1.Spring MVC加载了多个配置文件导致的,并不是版本问题 ...

  6. ScSPM

    Linear Spatial Pyramid Matching using Sparse Coding for Image Classification (CVPR'09) 稀疏编码系列: (一)-- ...

  7. Solidworks如何制作动画2

    切换到Motion Study,然后定位到任意一帧,然后就可以摆弄当前装配体到新的位置和姿态,然后此时的时间和姿态就被记录下来了.以此类推可以多做几帧. 动画做好之后,点击播放可以预览.如果要保存,先 ...

  8. 创建一个简单的 http 服务器

    创建一个简单的 http 服务器 直接在 目录下运行 当前的目录即可是root 目录 默认端口8000 应该可以加参数修改端口号 Python2 python -m SimpleHTTPServer ...

  9. Android中怎样自己制作su

    本文原博客:http://hubingforever.blog.163.com/blog/static/171040579201372915716149/ 在Android源代码的system\ext ...

  10. ITOO高校云平台之考评系统项目总结

    高校云平台,将云的概念引入到我的生活, 高校云平台主要是以各大高校的业务为基础设计开发,包含权限系统,基础系统.新生入学系统.考评系统,成绩系统.选课系统,视频课系统.3月份參加云平台3.0的开发,至 ...