值得注意的是:

一个点的子树是存在一起的。。。也就是说我们修改子树的时候只用。。。

  1. /**************************************************************
  2. Problem: 1036
  3. User: Ez3real
  4. Language: C++
  5. Result: Accepted
  6. Time:3068 ms
  7. Memory:8112 kb
  8. ****************************************************************/
  9.  
  10. #include<iostream>
  11. #include<cstdio>
  12. #include<cstdlib>
  13. #include<cmath>
  14. #include<cstring>
  15. #include<algorithm>
  16. #define l(x) (x<<1)
  17. #define r(x) ((x<<1)|1)
  18. #define ll long long
  19. using namespace std;
  20. struct Treenode{int l,r;ll tag,val,mx;};
  21. struct Segtree
  22. {
  23. Treenode tr[*];
  24. void pushup(int id){tr[id].val=tr[l(id)].val+tr[r(id)].val;}
  25. void pushdown(int id)
  26. {
  27. tr[l(id)].val+=tr[id].tag*(tr[l(id)].r-tr[l(id)].l+);
  28. tr[r(id)].val+=tr[id].tag*(tr[r(id)].r-tr[r(id)].l+);
  29. tr[l(id)].tag+=tr[id].tag;tr[r(id)].tag+=tr[id].tag;
  30. tr[id].tag=;
  31. }
  32. void build(int id,int L,int R)
  33. {
  34. tr[id].l=L,tr[id].r=R;
  35. tr[id].tag=;
  36. if(L==R)return;
  37. int mid=(L+R)>>;
  38. build(l(id),L,mid);
  39. build(r(id),mid+,R);
  40. pushup(id);
  41. }
  42. void update(int id,int L,int R,ll k)
  43. {
  44. if(tr[id].l>=L && tr[id].r<=R)
  45. {
  46. tr[id].val+=k*(tr[id].r-tr[id].l+);
  47. tr[id].tag+=k;
  48. return;
  49. }
  50. if(tr[id].tag)pushdown(id);
  51. int mid=(tr[id].l+tr[id].r)>>;
  52. if(L<=mid)update(l(id),L,R,k);
  53. if(R>mid) update(r(id),L,R,k);
  54. pushup(id);
  55. }
  56. ll query(int id,int L,int R)
  57. {
  58. if(tr[id].l>=L && tr[id].r<=R)return tr[id].val;
  59. if(tr[id].tag)pushdown(id);
  60. int mid=(tr[id].l+tr[id].r)>>;
  61. ll ans=;
  62. if(L<=mid)ans+=query(l(id),L,R);
  63. if(R>mid)ans+=query(r(id),L,R);
  64. return ans;
  65. }
  66. }Seg;
  67.  
  68. int first[],to[*],next[*];
  69. ll val[*],cnt;
  70. int size[],depth[],fa[],pos[],bl[],sz;
  71. inline void add(int u,int v){to[++cnt]=v;next[cnt]=first[u];first[u]=cnt;}
  72. int n,q,r,P;
  73. inline void dfs1(int u)
  74. {
  75. size[u]=;
  76. for(int i=first[u];i;i=next[i])
  77. {
  78. if(to[i]==fa[u])continue;
  79. depth[to[i]]=depth[u]+;
  80. fa[to[i]]=u;
  81. dfs1(to[i]);
  82. size[u]+=size[to[i]];
  83. }
  84. }
  85. inline void dfs2(int u,int idc)
  86. {
  87. int k=;
  88. sz++;
  89. pos[u]=sz;
  90. bl[u]=idc;
  91. for(int i=first[u];i;i=next[i])
  92. if(depth[to[i]]>depth[u] && size[to[i]]>size[k])
  93. k=to[i];
  94.  
  95. if(k==)return;
  96. dfs2(k,idc);
  97. for(int i=first[u];i;i=next[i])
  98. if(depth[to[i]]>depth[u] && k!=to[i])
  99. dfs2(to[i],to[i]);
  100. }
  101. void tradd(ll x,ll v){Seg.update(,pos[x],pos[x]+size[x]-,v);}
  102. ll trq(ll x){return Seg.query(,pos[x],pos[x]+size[x]-)%P;}
  103. void Chainadd(ll x,ll y,ll v)
  104. {
  105. while(bl[x]!=bl[y])
  106. {
  107. if(depth[bl[x]]<depth[bl[y]]){x^=y;y^=x;x^=y;}
  108. Seg.update(,pos[bl[x]],pos[x],v);
  109. x=fa[bl[x]];
  110. }
  111. if(depth[x]<depth[y]){x^=y;y^=x;x^=y;}
  112. Seg.update(,pos[y],pos[x],v);
  113. }
  114. ll Qsum(ll u,ll v)
  115. {
  116. ll sum=;
  117. while(bl[u]!=bl[v])
  118. {
  119. if(depth[bl[u]]<depth[bl[v]]){u^=v;v^=u;u^=v;}
  120. (sum+=Seg.query(,pos[bl[u]],pos[u]))%=P;
  121. u=fa[bl[u]];
  122. }
  123. if(depth[u]<depth[v]){u^=v;v^=u;u^=v;}
  124. (sum+=Seg.query(,pos[v],pos[u]))%=P;
  125. return sum;
  126. }
  127. void Solve()
  128. {
  129. scanf("%d%d%d%d",&n,&q,&r,&P);
  130. for(int i=;i<=n;i++)scanf("%lld",&val[i]);
  131. for(int i=;i<n;i++)
  132. {
  133. int x,y;
  134. scanf("%d%d",&x,&y);
  135. add(x,y);
  136. add(y,x);
  137. }
  138. depth[r]=;
  139. dfs1(r);
  140. dfs2(r,r);
  141. Seg.build(,,n);
  142. for(int i=;i<=n;i++)Seg.update(,pos[i],pos[i],val[i]);
  143. for(int i=;i<=q;i++)
  144. {
  145. int opt;
  146. scanf("%d",&opt);
  147. if(opt==)
  148. {
  149. ll x,y,w;
  150. scanf("%lld%lld%lld",&x,&y,&w);
  151. Chainadd(x,y,w);
  152. }
  153. if(opt==)
  154. {
  155. ll x,y;
  156. scanf("%lld%lld",&x,&y);
  157. printf("%lld\n",Qsum(x,y));
  158. }
  159. if(opt==)
  160. {
  161. ll x,v;
  162. scanf("%lld%lld",&x,&v);
  163. tradd(x,v);
  164. }
  165. if(opt==)
  166. {
  167. ll x;
  168. scanf("%lld",&x);
  169. printf("%lld\n",trq(x));
  170. }
  171. }
  172. }
  173. int main()
  174. {
  175. Solve();
  176. return ;
  177. }

Luogu3384

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<cstring>
  6. #include<algorithm>
  7. #define l(x) (x<<1)
  8. #define r(x) ((x<<1)|1)
  9. #define ll long long
  10. using namespace std;
  11.  
  12. struct Treenode{int l,r;ll tag,val,mx;};
  13. struct Segtree
  14. {
  15. Treenode tr[*];
  16. void pushup(int id){tr[id].val=tr[l(id)].val+tr[r(id)].val;tr[id].mx=max(tr[l(id)].mx,tr[r(id)].mx);}
  17. void build(int id,int L,int R)
  18. {
  19. tr[id].l=L,tr[id].r=R;
  20. if(L==R)return;
  21. int mid=(L+R)>>;
  22. build(l(id),L,mid);
  23. build(r(id),mid+,R);
  24. pushup(id);
  25. }
  26. void update(int k,int x,int y)
  27. {
  28. int l=tr[k].l,r=tr[k].r,mid=(l+r)>>;
  29. if(l==r){tr[k].val=tr[k].mx=y;return;}
  30. if(x<=mid)update(k<<,x,y);
  31. else update(k<<|,x,y);
  32. tr[k].val=tr[k<<].val+tr[k<<|].val;
  33. tr[k].mx=max(tr[k<<].mx,tr[k<<|].mx);
  34. }
  35. int query(int id,int L,int R)
  36. {
  37. if(tr[id].l>=L && tr[id].r<=R)return tr[id].val;
  38. int mid=(tr[id].l+tr[id].r)>>;
  39. int ans=;
  40. if(L<=mid)ans+=query(l(id),L,R);
  41. if(R>mid)ans+=query(r(id),L,R);
  42. return ans;
  43. }
  44. int Query(int id,int L,int R)
  45. {
  46. if(tr[id].l>=L && tr[id].r<=R)return tr[id].mx;
  47. int mid=(tr[id].l+tr[id].r)>>;
  48. int ans=-;
  49. if(L<=mid)ans=max(ans,Query(l(id),L,R));
  50. if(R>mid)ans=max(ans,Query(r(id),L,R));
  51. return ans;
  52. }
  53. }Seg;
  54.  
  55. int first[],to[*],next[*],val[*],cnt;
  56. int size[],depth[],fa[],pos[],bl[],sz;
  57. inline void add(int u,int v){to[++cnt]=v;next[cnt]=first[u];first[u]=cnt;}
  58. inline void dfs1(int u)
  59. {
  60. size[u]=;
  61. for(int i=first[u];i;i=next[i])
  62. {
  63. if(to[i]==fa[u])continue;
  64. depth[to[i]]=depth[u]+;
  65. fa[to[i]]=u;
  66. dfs1(to[i]);
  67. size[u]+=size[to[i]];
  68. }
  69. }
  70. inline void dfs2(int u,int idc)
  71. {
  72. int k=;
  73. sz++;
  74. pos[u]=sz;
  75. bl[u]=idc;
  76. for(int i=first[u];i;i=next[i])
  77. if(depth[to[i]]>depth[u] && size[to[i]]>size[k])
  78. k=to[i];
  79.  
  80. if(k==)return;
  81. dfs2(k,idc);
  82. for(int i=first[u];i;i=next[i])
  83. if(depth[to[i]]>depth[u] && k!=to[i])
  84. dfs2(to[i],to[i]);
  85. }
  86. int Qsum(int u,int v)
  87. {
  88. int sum=;
  89. while(bl[u]!=bl[v])
  90. {
  91. if(depth[bl[u]]<depth[bl[v]]){u^=v;v^=u;u^=v;}
  92. sum+=Seg.query(,pos[bl[u]],pos[u]);
  93. u=fa[bl[u]];
  94. }
  95. if(pos[u]>pos[v]){u^=v;v^=u;u^=v;}
  96. sum+=Seg.query(,pos[u],pos[v]);
  97. return sum;
  98. }
  99. int Qmax(int u,int v)
  100. {
  101. int mx=-;
  102. while(bl[u]!=bl[v])
  103. {
  104. if(depth[bl[u]]<depth[bl[v]]){u^=v;v^=u;u^=v;}
  105. mx=max(mx,Seg.Query(,pos[bl[u]],pos[u]));
  106. u=fa[bl[u]];
  107. }
  108. if(pos[u]>pos[v]){u^=v;v^=u;u^=v;}
  109. mx=max(mx,Seg.Query(,pos[u],pos[v]));
  110. return mx;
  111. }
  112. int n,q;
  113. void Solve()
  114. {
  115. scanf("%d",&n);
  116. for(int i=;i<n;i++)
  117. {
  118. int x,y;
  119. scanf("%d%d",&x,&y);
  120. add(x,y);
  121. add(y,x);
  122. }
  123. for(int i=;i<=n;i++)scanf("%d",&val[i]);
  124. dfs1();
  125. dfs2(,);
  126. Seg.build(,,n);
  127. for(int i=;i<=n;i++)Seg.update(,pos[i],val[i]);
  128. scanf("%d",&q);
  129. char ch[];
  130. for(int i=;i<=q;i++)
  131. {
  132. int x,y;scanf("%s%d%d",ch,&x,&y);
  133. if(ch[]=='C'){val[x]=y;Seg.update(,pos[x],y);}
  134. else
  135. {
  136. if(ch[]=='M')printf("%d\n",Qmax(x,y));
  137. else printf("%d\n",Qsum(x,y));
  138. }
  139. }
  140. }
  141. int main()
  142. {
  143. Solve();
  144. return ;
  145. }

bzoj1036

洛谷3384&bzoj1036树链剖分的更多相关文章

  1. 洛谷P3979 遥远的国度 树链剖分+分类讨论

    题意:给出一棵树,这棵树每个点有权值,然后有3种操作.操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值. 解法:如果没有修改树根操作那么这题就是树链剖 ...

  2. 洛谷 P4114 Qtree1 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例: 输出样例: 说明 说明 思路 Change Query AC代码 总结 题面 题目链接 P4114 Qt ...

  3. [洛谷P3384] [模板] 树链剖分

    题目传送门 显然是一道模板题. 然而索引出现了错误,狂wa不止. 感谢神犇Dr_J指正.%%%orz. 建线段树的时候,第44行. 把sum[p]=bv[pos[l]]%mod;打成了sum[p]=b ...

  4. 洛谷.4114.Qtree1(树链剖分)

    题目链接 模板题都错了这么多次.. //边权赋到点上 树剖模板 //注意LCA.链的顶端不能统计到答案! #include <cstdio> #include <cctype> ...

  5. 洛谷 P3384 【模板】树链剖分

    树链剖分 将一棵树的每个节点到它所有子节点中子树和(所包含的点的个数)最大的那个子节点的这条边标记为"重边". 将其他的边标记为"轻边". 若果一个非根节点的子 ...

  6. 树链剖分详解(洛谷模板 P3384)

    洛谷·[模板]树链剖分 写在前面 首先,在学树链剖分之前最好先把 LCA.树形DP.DFS序 这三个知识点学了 emm还有必备的 链式前向星.线段树 也要先学了. 如果这三个知识点没掌握好的话,树链剖 ...

  7. ⌈洛谷1505⌋⌈BZOJ2157⌋⌈国家集训队⌋旅游【树链剖分】

    题目链接 [洛谷] [BZOJ] 题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T ...

  8. BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...

  9. 【算法学习】【洛谷】树链剖分 & P3384 【模板】树链剖分 P2146 软件包管理器

    刚学的好玩算法,AC2题,非常开心. 其实很早就有教过,以前以为很难就没有学,现在发现其实很简单也很有用. 更重要的是我很好调试,两题都是几乎一遍过的. 介绍树链剖分前,先确保已经学会以下基本技巧: ...

随机推荐

  1. vuforia 中摄像机的开启与关闭

    本文主要讲解的是Unity对Vuforia的开发中在原生调用摄像头上遇到的坑~Unity中调用设备摄像头打开或则关闭,或则开关扫描识别问题等等一些情况~ 下面先说说趟过的坑,再说说解决办法,或则目前没 ...

  2. 自定义列表数据自动循环向下滚动view(类似于通知通报消息)

    首先申明,这个自定义View不是本人写的,大神写的,本人仅限学习一级研究使用 直接上代码吧!后面我再解释一遍 package com.egojit.android.gcoa.views; import ...

  3. Idiomatic Phrases Game(图论最短路)

    Idiomatic Phrases Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/O ...

  4. 记录-spring MultipartFile 文件上传

    注意:以下上传和下载方法未必完全正确,不同浏览器效果不同,建议不要使用IE /** * 简单的文件上传 * @author:qiuchen * @createTime:2012-6-19 * @par ...

  5. 如何更改CSDN博客高亮代码皮肤的样式,使博客看起来更有范(推荐)

    由于本人写博客的时候,也没有配置博客的相关属性,因此贴出来的代码块都是CSDN默认的,因此代码背景色都是白色的,如下所示: 但是本人在浏览他人博客的时候,发现有些博客的代码块看起来比较有范,整个代码库 ...

  6. C#练习委托、事件、事件处理

    控制台应用程序效果: 代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

  7. mail

    mail.php  <?php require_once('class.phpmailer.php'); $mail = new PHPMailer(); //实例化 $mail->IsS ...

  8. swift ! 和 ? 的学习

    刚开始学 这两个符号 不确定到底是否是可以互相替代 用的都混淆了 今天好好做个总结 如果声明一个变量 如下 var  name:String?  //只声明 没做初始化赋值 说明 当前name 是 n ...

  9. MySQL与Oracle的语法区别详细对比

    MySQL与Oracle的语法区别详细对比 Oracle和mysql的一些简单命令对比在本文中将会涉及到很多的实例,感兴趣的你不妨学习一下,就当巩固自己的知识了   Oracle和mysql的一些简单 ...

  10. ELK日志分析系统-Logstack

    ELK日志分析系统 作者:Danbo 2016-*-* 本文是学习笔记,参考ELK Stack中文指南,链接:https://www.gitbook.com/book/chenryn/kibana-g ...