题目大意:

给定n个结点,有n-1条无向边,给定每条边的边权

两种操作,第一种:求任意两点之间路径的权值和,第二种:修改树上一点的权值。

因为是一棵树,可以直接把 u点和v点间(假设u为父节点,v为子节点)的边 的边权往下给v点

这样就转换成了点权,那么此时查询 u点到v点之间路径的权值和 的话

由于u点存有 u的父节点到u 的边权,所以应该查询的是 u到v的路径上 的第二个点到v的权值和

  1. 修改查询树上两结点间路径长度的函数
  2. int queryPath(int x,int y){ }
  3. 中求最后一步的部分
  4.  
  5. /// 点权版本
  6. if(p[x]>p[y]) swap(x,y);
  7. return ans+query(p[x],p[y],,pos,);
  8. /// 边权版本
  9. if(x==y) return ans;
  10. if(dep[x]>dep[y]) swap(x,y);
  11. return ans+query(p[son[x]],p[y],root);
  1. #include <stdio.h>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. #define mem(i,j) memset(i,j,sizeof(i))
  6. #define lson l,m,rt<<1
  7. #define rson m+1,r,rt<<1|1
  8. #define root 1,n,1
  9.  
  10. const int maxn=1e5+;
  11. int n,q,s;
  12.  
  13. struct QTree {
  14. struct EDGE { int to,ne; }e[maxn<<];
  15. int head[maxn], tot;
  16. void add(int u,int v) {
  17. e[tot].to=v;
  18. e[tot].ne=head[u];
  19. head[u]=tot++;
  20. }
  21.  
  22. int fa[maxn], son[maxn], dep[maxn], num[maxn];
  23. int top[maxn], p[maxn], fp[maxn], pos;
  24.  
  25. int sumT[maxn<<];
  26.  
  27. void init() {
  28. tot=; mem(head,);
  29. pos=; mem(son,);
  30. }
  31.  
  32. // --------------------以下是线段树-------------------------
  33.  
  34. void pushup(int rt) {
  35. sumT[rt]=sumT[rt<<]+sumT[rt<<|];
  36. }
  37. void build(int l,int r,int rt) {
  38. if(l==r) {
  39. sumT[rt]=; return ;
  40. }
  41. int m=(l+r)>>;
  42. build(lson), build(rson);
  43. pushup(rt);
  44. }
  45. void update(int k,int w,int l,int r,int rt) {
  46. if(l==r) {
  47. sumT[rt]=w; return;
  48. }
  49. int m=(l+r)>>;
  50. if(k<=m) update(k,w,lson);
  51. else update(k,w,rson);
  52. pushup(rt);
  53. }
  54. int query(int L,int R,int l,int r,int rt) {
  55. if(L<=l && r<=R) return sumT[rt];
  56. int m=(l+r)>>, res=;
  57. if(L<=m) res+=query(L,R,lson);
  58. if(R>m) res+=query(L,R,rson);
  59. return res;
  60. }
  61.  
  62. // --------------------以上是线段树-------------------------
  63.  
  64. // --------------------以下是树链剖分-------------------------
  65.  
  66. void dfs1(int u,int pre,int d) {
  67. dep[u]=d; fa[u]=pre; num[u]=;
  68. for(int i=head[u];i;i=e[i].ne) {
  69. int v=e[i].to;
  70. if(v!=fa[u]) {
  71. dfs1(v,u,d+);
  72. num[u]+=num[v];
  73. if(!son[u] || num[v]>num[son[u]])
  74. son[u]=v;
  75. }
  76. }
  77. }
  78. void dfs2(int u,int sp) {
  79. top[u]=sp; p[u]=++pos; fp[p[u]]=u;
  80. if(!son[u]) return;
  81. dfs2(son[u],sp);
  82. for(int i=head[u];i;i=e[i].ne) {
  83. int v=e[i].to;
  84. if(v!=son[u] && v!=fa[u])
  85. dfs2(v,v);
  86. }
  87. }
  88. int queryPath(int x,int y) {
  89. int ans=;
  90. int fx=top[x], fy=top[y];
  91. while(fx!=fy) {
  92. if(dep[fx]>=dep[fy]) {
  93. ans+=query(p[fx],p[x],root);
  94. x=fa[fx];
  95. } else {
  96. ans+=query(p[fy],p[y],root);
  97. y=fa[fy];
  98. }
  99. fx=top[x], fy=top[y];
  100. }
  101. if(x==y) return ans;
  102. if(dep[x]>dep[y]) swap(x,y);
  103. return ans+query(p[son[x]],p[y],root);
  104. }
  105.  
  106. // --------------------以上是树链剖分-------------------------
  107.  
  108. void initQTree() {
  109. dfs1(,,);
  110. dfs2(,);
  111. build(root);
  112. }
  113. }T;
  114. int E[maxn][];
  115.  
  116. int main()
  117. {
  118. while(~scanf("%d%d%d",&n,&q,&s)) {
  119. T.init();
  120. for(int i=;i<n;i++) {
  121. int u,v,w; scanf("%d%d%d",&u,&v,&w);
  122. E[i][]=u, E[i][]=v, E[i][]=w;
  123. T.add(u,v); T.add(v,u);
  124. }
  125. T.initQTree();
  126. for(int i=;i<n;i++) {
  127. if(T.dep[E[i][]]>T.dep[E[i][]])
  128. swap(E[i][],E[i][]);
  129. T.update(T.p[E[i][]],E[i][],root);
  130. }
  131. while(q--) {
  132. int op; scanf("%d",&op);
  133. if(op) {
  134. int k,w; scanf("%d%d",&k,&w);
  135. T.update(T.p[E[k][]],w,root);
  136. } else {
  137. int v; scanf("%d",&v);
  138. printf("%d\n",T.queryPath(s,v));
  139. s=v;
  140. }
  141. }
  142. }
  143.  
  144. return ;
  145. }

POJ 2763 /// 基于边权的树链剖分的更多相关文章

  1. POJ 2763:Housewife Wind(树链剖分)

    http://poj.org/problem?id=2763 题意:给出 n 个点, n-1 条带权边, 询问是询问 s 到 v 的权值, 修改是修改存储时候的第 i 条边的权值. 思路:树链剖分之修 ...

  2. HDU 3966 & POJ 3237 & HYSBZ 2243 & HRBUST 2064 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  3. fzu 2082 过路费 (树链剖分+线段树 边权)

    Problem 2082 过路费 Accept: 887    Submit: 2881Time Limit: 1000 mSec    Memory Limit : 32768 KB  Proble ...

  4. BZOJ 2157 旅行(树链剖分码农题)

    写了5KB,1发AC... 题意:给出一颗树,支持5种操作. 1.修改某条边的权值.2.将u到v的经过的边的权值取负.3.求u到v的经过的边的权值总和.4.求u到v的经过的边的权值最大值.5.求u到v ...

  5. POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...

  6. HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  7. POJ 3237 Tree (树链剖分)

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 2825   Accepted: 769 Description ...

  8. 【BZOJ-4353】Play with tree 树链剖分

    4353: Play with tree Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 31  Solved: 19[Submit][Status][ ...

  9. Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)

    Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...

随机推荐

  1. SQL生成 C# Model

    本文转自: https://www.cnblogs.com/jhli/p/11552105.html declare @TableName sysname = 'T_FakeOrderList' de ...

  2. HIve分组查询返回每组的一条记录

    select a.lng,a.lat from (select row_number() over ( partition by uid,grid_id) as rnum,weighted_centr ...

  3. CentOS6.8搭建LNMP环境

    selinux可能会致使编译安装失败,我们先禁用它.永久禁用,需要重启生效 sed -i ‘s/SELINUX=enforcing/SELINUX=disabled/g’ /etc/selinux/c ...

  4. 在Linux下面无法使用向上箭头自动补全上条命令

    会用^[[A替代. 参考:http://stackoverflow.com/a/8641302/941650

  5. 常用内置模块(四)——subprocess、re

    常用模块(四) 一.subprocess模块 1.subprocess为子流程模块,用于执行系统命令,该模块在Python全栈开发中不常用 2.常用方法 run 返回一个表示执行结果的对象 call ...

  6. keepalived 参数中文说明

    GLOBAL CONFIGURATION Global definitions global_defs { notification_email { admin@example.com } notif ...

  7. keep-alive用法及(activated,deactivated生命周期)

    <template> <div id="app"> <!-- <img src="./assets/logo.png"> ...

  8. redis String 相关命令

  9. 运行Storm实例

  10. 如何清除Windows共享登录的用户名密码

    打开cmd 1.[查看已记录的登录信息] net use 2.[清除记录] 得关掉你所有打开的samba之后再 net use * /del