poj2763

题意

给定一个树形图,某人原来在 s 点,每条边(路)有通过的时间花费,有两种操作:1. 查询某人到 u 点花费的时间 2. 更新某条路的时间花费。

分析

权值在边上,可以把它们 “转移” 到点上,对于一条边,让 \(dep\) 最大的点存储权值,比如说我们要更新 \((u, v)\) 这条路,如果 \(dep[u] > dep[v]\) ,更新 \(u\) 这个点对应的线段树的点即可。

将树映射到线段树上之后,本题就变成了单点更新,区间求和的线段树问题了。

code

  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 + 10;
  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] = 1; son[u] = 0;
  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] + 1;
  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 << 1] + sum[rt << 1 | 1];
  53. }
  54. void build(int l, int r, int rt) {
  55. sum[rt] = 0;
  56. if(l == r) return;
  57. int m = (l + r) / 2;
  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) / 2;
  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) / 2;
  73. ll res = 0;
  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, 1, n, 1);
  80. else update(w[e[v].v], c, 1, n, 1);
  81. }
  82. ll seek(int v, int u) {
  83. int t1 = top[v], t2 = top[u];
  84. ll res = 0;
  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], 1, n, 1);
  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], 1, n, 1);
  95. }
  96. int main() {
  97. memset(head, -1, sizeof head);
  98. cnt = num = 0;
  99. scanf("%d%d%d", &n, &q, &s);
  100. for(int i = 1; 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(1);
  106. build_tree(1, 1);
  107. build(1, n, 1);
  108. for(int i = 1; i < n; i++) {
  109. if(dep[e[i].u] > dep[e[i].v]) update(w[e[i].u], e[i].c, 1, n, 1);
  110. else update(w[e[i].v], e[i].c, 1, n, 1);
  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 0;
  126. }

poj2763(树链剖分 - 边权)的更多相关文章

  1. poj2763树链剖分边权+区间和

    自己写的比原来的板子常数小了不少嘻嘻,边权处理起来比点权要复杂一下 由于根节点没有被映射的边,其被访问到的顺序是0,直接排除在线段树外 #include<iostream> #includ ...

  2. POJ2763 Housewife Wind 树链剖分 边权

    POJ2763 Housewife Wind 树链剖分 边权 传送门:http://poj.org/problem?id=2763 题意: n个点的,n-1条边,有边权 修改单边边权 询问 输出 当前 ...

  3. BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时 ...

  4. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  5. POJ3237 Tree 树链剖分 边权

    POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...

  6. HDU3669 Aragorn's Story 树链剖分 点权

    HDU3669 Aragorn's Story 树链剖分 点权 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: n个点的,m条边,每个点都 ...

  7. BZOJ 1984: 月下“毛景树” [树链剖分 边权]

    1984: 月下“毛景树” Time Limit: 20 Sec  Memory Limit: 64 MBSubmit: 1728  Solved: 531[Submit][Status][Discu ...

  8. SPOJ 375 (树链剖分 - 边权剖分 - 修改单边权)

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#problem/I 给你一棵有边权的树,有两个操作:一个操作是输出l到 ...

  9. 树链剖分边权模板spoj375

    树链剖分是树分解成多条链来解决树上两点之间的路径上的问题 如何求出树链:第一次dfs求出树上每个结点的大小和深度和最大的儿子,第二次dfs就能将最大的儿子串起来并hash(映射)到线段树上(或者其他数 ...

  10. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

随机推荐

  1. [译]15-spring 自动装配

    前面的章节我们已经学习了如何使用bean元素在xml配置文件中声明一个bean.也学习了如何使用bean的子元素contructor-arg 和property进行bean的依赖项的注入. 之前bea ...

  2. diskimage-builder

    Supported Distributions Distributions which are supported as a build host: Centos 6, 7 Debian 8 (“je ...

  3. Thymeleaf 模板 在spring boot 中的引用和应用

    Thymeleaf是一个java类库,他是一个xml/xhtml/html5的模板引擎和Struts框架的freemarker模板类似,可以作为mvc的web应用的view层. Thymeleaf还提 ...

  4. PHP session 与cookie

    知识点: session是将服务器将网页产生的会话信息以数组形式存到一个php文件中,产生的全局变量,可以在系统下的其他网页任意调用这个数据. cookie类似于session原理,但是是将数据存给用 ...

  5. Batting Practice LightOJ - 1408

    Batting Practice LightOJ - 1408(概率dp) 题意:有无限个球,进球的概率为p,问你连续不进k1个球或者连续进k2个球需要使用的球的个数的期望 思路: \(定义f[i]表 ...

  6. [转]busybox登陆后没要求输入密码的解决办法

    转自:http://blog.chinaunix.net/uid-8058395-id-65785.html 1.制作好ramdisk之后 通过串口进入系统 却发现系统直接登录进去了 并没有要求用ro ...

  7. [LeetCode169]Majority Element

    Majority Element Total Accepted: 58500 Total Submissions: 163658My Submissions Question Solution  Gi ...

  8. CSU 2031

    2031: Barareh on Fire Submit Page   Summary   Time Limit: 3 Sec     Memory Limit: 512 Mb     Submitt ...

  9. DotNETCore 学习笔记 路由

    Route ------------------------------------------constraint------------------------------------------ ...

  10. Oracle 数据库维护相关

    版本升级 在维护数据库升级的过程中,会产生n个脚本.谈谈我所处的项目背景,项目数据库最早版本假定为1,最后在多次维护后,版本号,可能变更为16.那么针对项目上不同的数据库版本,如何来进行升级呢? 我使 ...