题意: 知道了一颗有  n 个节点的树和树上每条边的权值,对应两种操作:

0 x        输出 当前节点到 x节点的最短距离,并移动到 x 节点位置

1 x val   把第 x 条边的权值改为 val

题意: 知道了一颗有  n 个节点的树和树上每条边的权值,对应两种操作:

0 x        输出 当前节点到 x节点的最短距离,并移动到 x 节点位置

1 x val   把第 x 条边的权值改为 val

LCA +RMQ+树状数组

  1. #include <cstdio>
  2. #include <cmath>
  3. #include <cstring>
  4. #include <algorithm>
  5.  
  6. using namespace std;
  7.  
  8. const int maxn = 2e5+;
  9.  
  10. int N,Q,S;
  11. //vector <int> G[maxn];
  12.  
  13. struct edge{
  14. int to,next,w;
  15. }e[*maxn];
  16.  
  17. int head[*maxn],tot;
  18. void add_edge(int u,int v,int w)
  19. {
  20. e[tot].to = v;
  21. e[tot].w = w;
  22. e[tot].next = head[u];
  23. head[u] = tot++;
  24.  
  25. e[tot].to = u;
  26. e[tot].w = w;
  27. e[tot].next = head[v];
  28. head[v] = tot++;
  29. }
  30.  
  31. int in[maxn],out[maxn],P[*maxn],fa[maxn][],dep[maxn],dis[maxn],cnt;
  32. void dfs(int u,int _fa,int _dep,int _dis)
  33. {
  34. in[u] = ++cnt;
  35. P[cnt] = u;
  36. fa[u][] = _fa;
  37. dis[u] = _dis;
  38. dep[u] = _dep;
  39. for(int i=head[u];~i;i=e[i].next)
  40. {
  41. int v = e[i].to;
  42. if(v == _fa) continue;
  43. dfs(v,u,_dep+,_dis+e[i].w);
  44. }
  45. out[u] = ++cnt;
  46. }
  47. void debug()
  48. {
  49. printf("in:\t");for(int i=;i<=N;i++) printf("%d ",in[i]);puts("");
  50. printf("out:\t");for(int i=;i<=N;i++) printf("%d ",out[i]);puts("");
  51. printf("p:\t");for(int i=;i<=cnt;i++) printf("%d ",P[i]);puts("");
  52. printf("dis:\t");for(int i=;i<=N;i++) printf("%d ",dis[i]);puts("");
  53. printf("dep:\t");for(int i=;i<=N;i++) printf("%d ",dep[i]);puts("");
  54. printf("edge:");for(int i=;i<tot;i++) printf("\tto:%d w:%d\n",e[i].to,e[i].w);
  55. }
  56.  
  57. int initLCA()
  58. {
  59. int m = (int)log(N)/log()+;
  60. for(int k=;k<m;k++)
  61. {
  62. for(int v=;v<=N;v++)
  63. {
  64. if(fa[v][k] < ) {fa[v][k+] = -;continue;}
  65. else fa[v][k+] = fa[fa[v][k]][k];
  66. }
  67. }
  68. }
  69.  
  70. int LCA(int u,int v)
  71. {
  72. int m = (int)log(N)/log()+;
  73. if(dep[v] > dep[u]) swap(u,v);
  74. for(int k=;k<m;k++)
  75. {
  76. if((dep[u]-dep[v])>>k & )
  77. u = fa[u][k];
  78. }
  79. if(u == v) return u;
  80. for(int k=m-;k>=;k--)
  81. {
  82. if(fa[u][k] != fa[v][k])
  83. {
  84. u = fa[u][k];
  85. v = fa[v][k];
  86. }
  87. }
  88. return fa[u][];
  89. }
  90.  
  91. int c[*maxn];
  92. int lowbit(int x) {return x&-x;}
  93.  
  94. void init()
  95. {
  96. memset(head,-,sizeof head);
  97. memset(fa,-,sizeof fa);
  98. memset(c,,sizeof c);
  99. memset(in,,sizeof in);
  100. memset(out,,sizeof out);
  101. tot = ;
  102. cnt = ;
  103. }
  104.  
  105. void add(int x,int d)
  106. {
  107. while(x)
  108. {
  109. c[x] += d;
  110. x -= lowbit(x);
  111. }
  112. }
  113. void add_seg(int l,int r,int d)
  114. {
  115. add(r,d);
  116. add(l-,-d);
  117. }
  118. int sum(int x)
  119. {
  120. int res = ;
  121. //printf("u:%d ",P[x]);
  122. while(x <= cnt)
  123. {
  124. res += c[x];
  125. x += lowbit(x);
  126. }
  127. //printf("res:%d\n",res);
  128. return res;
  129. }
  130. int dist(int x)
  131. {
  132. if(x == -) return ;
  133. return sum(in[x]) + dis[x];
  134. }
  135. int main()
  136. {
  137. //freopen("input.txt","r",stdin);
  138. while(~scanf("%d%d%d",&N,&Q,&S))
  139. {
  140. init();
  141. for(int i=,u,v,w;i<N-;i++)
  142. {
  143. scanf("%d%d%d",&u,&v,&w);
  144. add_edge(u,v,w);
  145. }
  146. dfs(,-,,);
  147. //debug();
  148. initLCA();
  149. for(int i=;i<tot;i+=)
  150. {
  151. if(dep[e[i].to] < dep[e[i+].to]) swap(e[i].to,e[i+].to);
  152. }
  153. int op;
  154. for(int i=,a,b,c;i<Q;i++)
  155. {
  156. scanf("%d",&op);
  157. if(op == )
  158. {
  159. scanf("%d",&a);
  160. int lca = LCA(S,a);
  161. //printf("lca:%d\n",lca);
  162.  
  163. printf("%d\n",dist(S)+dist(a)-*(dist(lca)));
  164. S = a;
  165. }else
  166. {
  167. scanf("%d%d",&a,&b);
  168. a--;
  169. int u = e[a*].to;
  170. int dw = b - (dist(u) - dist(fa[u][]));
  171. //printf("dw:%d u:%d\n",dw,u);
  172. add_seg(in[u],out[u],dw);
  173. }
  174. }
  175. }
  176. }

树链部分

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. #define lson l, m, rt << 1
  5. #define rson m + 1, r, rt << 1 | 1
  6. using namespace std;
  7. typedef long long ll;
  8. const int MAXN = 2e5 + ;
  9. int n, q, s;
  10. int fa[MAXN]; // fa[v]: v 的父亲
  11. int dep[MAXN]; // dep[v]: v 的深度(根深度为1)
  12. int siz[MAXN]; // : 以 v 为根的子树的节点数
  13. int son[MAXN]; // : 重儿子,siz[u] 为 v 的子节点中 siz 值最大的,那么 u 就是 v 的重儿子
  14. int top[MAXN]; // : 表示 v 所在的重链的顶端节点
  15. int w[MAXN]; // : 表示 v 与其父亲节点的连边在线段树中的位置
  16. int num; // 将树映射到线段树上的标号
  17. int cnt, head[MAXN];
  18. struct Edge {
  19. int to, next;
  20. }edge[MAXN];
  21. struct E {
  22. int u, v, c;
  23. }e[MAXN];
  24. void addedge(int u, int v) {
  25. edge[cnt].to = v;
  26. edge[cnt].next = head[u];
  27. head[u] = cnt++;
  28. }
  29. void dfs(int u) {
  30. siz[u] = ; son[u] = ;
  31. for(int i = head[u]; ~i; i = edge[i].next) {
  32. if(edge[i].to != fa[u]) {
  33. fa[edge[i].to] = u;
  34. dep[edge[i].to] = dep[u] + ;
  35. dfs(edge[i].to);
  36. if(siz[edge[i].to] > siz[son[u]]) son[u] = edge[i].to;
  37. siz[u] += siz[edge[i].to];
  38. }
  39. }
  40. }
  41. void build_tree(int u, int tp) {
  42. w[u] = ++num; top[u] = tp;
  43. if(son[u]) build_tree(son[u], top[u]); // 使重链各边在线段树中呈连续分布
  44. for(int i = head[u]; ~i; i = edge[i].next) {
  45. int v = edge[i].to;
  46. if(v != son[u] && v != fa[u])
  47. build_tree(v, v);
  48. }
  49. }
  50. ll sum[MAXN];
  51. void pushUp(int rt) {
  52. sum[rt] = sum[rt << ] + sum[rt << | ];
  53. }
  54. void build(int l, int r, int rt) {
  55. sum[rt] = ;
  56. if(l == r) return;
  57. int m = (l + r) / ;
  58. build(lson); build(rson);
  59. }
  60. void update(int p, int c, int l, int r, int rt) {
  61. if(l == r) {
  62. sum[rt] = c;
  63. return;
  64. }
  65. int m = (l + r) / ;
  66. if(m >= p) update(p, c, lson);
  67. else update(p, c, rson);
  68. pushUp(rt);
  69. }
  70. ll query(int L, int R, int l, int r, int rt) {
  71. if(L <= l && R >= r) return sum[rt];
  72. int m = (l + r) / ;
  73. ll res = ;
  74. if(m >= L) res += query(L, R, lson);
  75. if(m < R) res += query(L, R, rson);
  76. return res;
  77. }
  78. void change(int v, int c) {
  79. if(dep[e[v].u] > dep[e[v].v]) update(w[e[v].u], c, , n, );
  80. else update(w[e[v].v], c, , n, );
  81. }
  82. ll seek(int v, int u) {
  83. int t1 = top[v], t2 = top[u];
  84. ll res = ;
  85. while(t1 != t2) {
  86. if(dep[t1] < dep[t2]) {
  87. swap(t1, t2); swap(v, u);
  88. }
  89. res += query(w[t1], w[v], , n, );
  90. v = fa[t1]; t1 = top[v];
  91. }
  92. if(v == u) return res;
  93. if(dep[v] > dep[u]) swap(v, u);
  94. return res + query(w[son[v]], w[u], , n, );
  95. }
  96. int main() {
  97. memset(head, -, sizeof head);
  98. cnt = num = ;
  99. scanf("%d%d%d", &n, &q, &s);
  100. for(int i = ; i < n; i++) {
  101. scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].c);
  102. addedge(e[i].u, e[i].v);
  103. addedge(e[i].v, e[i].u);
  104. }
  105. dfs();
  106. build_tree(, );
  107. build(, n, );
  108. for(int i = ; i < n; i++) {
  109. if(dep[e[i].u] > dep[e[i].v]) update(w[e[i].u], e[i].c, , n, );
  110. else update(w[e[i].v], e[i].c, , n, );
  111. }
  112. while(q--) {
  113. int cc;
  114. int x, y;
  115. scanf("%d", &cc);
  116. if(cc) {
  117. scanf("%d%d", &x, &y);
  118. change(x, y);
  119. } else {
  120. scanf("%d", &x);
  121. printf("%lld\n", seek(s, x));
  122. s = x;
  123. }
  124. }
  125. return ;
  126. }

POJ 2763 (LCA +RMQ+树状数组 || 树链部分) 查询两点距离+修改边权的更多相关文章

  1. 洛谷P3250 [HNOI2016]网络(整体二分+树状数组+树剖)

    传送门 据说正解是树剖套堆???然而代码看着稍微有那么一点点长…… 考虑一下整体二分,设当前二分到的答案为$mid$,如果所有大于$mid$的边都经过当前点$x$,那么此时$x$的答案必定小于等于$m ...

  2. 模拟赛 T3 DFS序+树状数组+树链的并+点权/边权技巧

    题意:给定一颗树,有 $m$ 次操作. 操作 0 :向集合 $S$ 中加入一条路径 $(p,q)$,权值为 $v$ 操作 1 :给定一个点集 $T$,求 $T$ 的并集与 $S$ 中路径含交集的权和. ...

  3. HDU 4031 Attack(线段树/树状数组区间更新单点查询+暴力)

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Sub ...

  4. NBOJv2 1050 Just Go(线段树/树状数组区间更新单点查询)

    Problem 1050: Just Go Time Limits:  3000 MS   Memory Limits:  65536 KB 64-bit interger IO format:  % ...

  5. UOJ#291. 【ZJOI2017】树状数组 树套树

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ291.html 题解 结论:这个写错的树状数组支持的是后缀加和后缀求和.这里的后缀求和在 x = 0 的时 ...

  6. hdu1556 树状数组区间更新单点查询板子

    就是裸的区间更新: 相对于直观的线段树的区间更新,树状数组的区间更新原理不太相同:由于数组中的一个结点控制的是一块区间,当遇到更新[l,r]时,先将所有能控制到 l 的结点给更新了,这样一来就是一下子 ...

  7. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  8. 【poj2155】Matrix(二维树状数组区间更新+单点查询)

    Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the ...

  9. hdu-3584 Cube---三维树状数组+区域更新单点查询

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3584 题目大意: 给定一个N*N*N多维数据集A,其元素是0或是1.A[i,j,k]表示集合中第 i ...

随机推荐

  1. opennebula 发送序列化ID,构造json格式错误

  2. linux下mariadb的下载与卸载

    Linux下mariadb的安装 使用阿里云的mariadb yum install mariadb-server mariadb -y 启动mariadb数据库 systemctl start/st ...

  3. C# 随机数 Radom 循环生成同一的数字

    错误:在一个循环结构中,利用下列代码生成随机数,发生生成的随机数是一样的! for (int i = 0; i < myArray.Length; i++) //给数组赋值 { Random m ...

  4. layui之弹出层--从父窗口传递数据到子窗口

    原文链接:https://blog.csdn.net/Code_shadow/article/details/80524633 var Index = layer.open({ title: &quo ...

  5. 杨辉三角的Python实现

      杨辉三角的Python实现 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 Python生成器实现杨辉三角: # python def yanghui_tr ...

  6. Kubernetes 集群部署(2) -- Etcd 集群

    Kubenetes 集群部署规划: 192.168.137.81  Master 192.168.137.82  Node 192.168.137.83  Node 以下在 Master 节点操作. ...

  7. 通过 js 修改 html 的文本内容或者样式

    通过 js 修改 html 的文本内容 <!DOCTYPE html> <html> <head> <meta charset="utf-8&quo ...

  8. 【bzoj3576】[Hnoi2014]江南乐 数论分块+博弈论

    Description 小A是一个名副其实的狂热的回合制游戏玩家.在获得了许多回合制游戏的世界级奖项之后,小A有一天突然想起了他小时候在江南玩过的一个回合制游戏. 游戏的规则是这样的,首先给定一个数F ...

  9. uoj #297. 【CTSC2017】密钥

    #297. [CTSC2017]密钥 一个密钥是一个长度为 n=2k+1n=2k+1 的字符串,它包含 11 个字母X.kk 个字母 A 和 kk 个字母 B.例如 k=3k=3 时,BAXABAB ...

  10. WKWebView 的使用和封装

    WKWebView 的使用和封装 前言 项目中有个新闻资讯模块展示公司和相关行业的最新动态. 这个部分基本是以展示网页为主,内部可能会有一些 native 和 JS 代码的交互. 因为是新项目,所以决 ...