poj2763

题意

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

分析

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

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

code

#include<cstdio>
#include<algorithm>
#include<cstring>
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 10;
int n, q, s;
int fa[MAXN]; // fa[v]: v 的父亲
int dep[MAXN]; // dep[v]: v 的深度(根深度为1)
int siz[MAXN]; // : 以 v 为根的子树的节点数
int son[MAXN]; // : 重儿子,siz[u] 为 v 的子节点中 siz 值最大的,那么 u 就是 v 的重儿子
int top[MAXN]; // : 表示 v 所在的重链的顶端节点
int w[MAXN]; // : 表示 v 与其父亲节点的连边在线段树中的位置
int num; // 将树映射到线段树上的标号
int cnt, head[MAXN];
struct Edge {
int to, next;
}edge[MAXN];
struct E {
int u, v, c;
}e[MAXN];
void addedge(int u, int v) {
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void dfs(int u) {
siz[u] = 1; son[u] = 0;
for(int i = head[u]; ~i; i = edge[i].next) {
if(edge[i].to != fa[u]) {
fa[edge[i].to] = u;
dep[edge[i].to] = dep[u] + 1;
dfs(edge[i].to);
if(siz[edge[i].to] > siz[son[u]]) son[u] = edge[i].to;
siz[u] += siz[edge[i].to];
}
}
}
void build_tree(int u, int tp) {
w[u] = ++num; top[u] = tp;
if(son[u]) build_tree(son[u], top[u]); // 使重链各边在线段树中呈连续分布
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(v != son[u] && v != fa[u])
build_tree(v, v);
}
}
ll sum[MAXN];
void pushUp(int rt) {
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void build(int l, int r, int rt) {
sum[rt] = 0;
if(l == r) return;
int m = (l + r) / 2;
build(lson); build(rson);
}
void update(int p, int c, int l, int r, int rt) {
if(l == r) {
sum[rt] = c;
return;
}
int m = (l + r) / 2;
if(m >= p) update(p, c, lson);
else update(p, c, rson);
pushUp(rt);
}
ll query(int L, int R, int l, int r, int rt) {
if(L <= l && R >= r) return sum[rt];
int m = (l + r) / 2;
ll res = 0;
if(m >= L) res += query(L, R, lson);
if(m < R) res += query(L, R, rson);
return res;
}
void change(int v, int c) {
if(dep[e[v].u] > dep[e[v].v]) update(w[e[v].u], c, 1, n, 1);
else update(w[e[v].v], c, 1, n, 1);
}
ll seek(int v, int u) {
int t1 = top[v], t2 = top[u];
ll res = 0;
while(t1 != t2) {
if(dep[t1] < dep[t2]) {
swap(t1, t2); swap(v, u);
}
res += query(w[t1], w[v], 1, n, 1);
v = fa[t1]; t1 = top[v];
}
if(v == u) return res;
if(dep[v] > dep[u]) swap(v, u);
return res + query(w[son[v]], w[u], 1, n, 1);
}
int main() {
memset(head, -1, sizeof head);
cnt = num = 0;
scanf("%d%d%d", &n, &q, &s);
for(int i = 1; i < n; i++) {
scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].c);
addedge(e[i].u, e[i].v);
addedge(e[i].v, e[i].u);
}
dfs(1);
build_tree(1, 1);
build(1, n, 1);
for(int i = 1; i < n; i++) {
if(dep[e[i].u] > dep[e[i].v]) update(w[e[i].u], e[i].c, 1, n, 1);
else update(w[e[i].v], e[i].c, 1, n, 1);
}
while(q--) {
int cc;
int x, y;
scanf("%d", &cc);
if(cc) {
scanf("%d%d", &x, &y);
change(x, y);
} else {
scanf("%d", &x);
printf("%lld\n", seek(s, x));
s = x;
}
}
return 0;
}

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. php导出数据为CSV文件DEMO

    代码示例: private function _download_send_headers($filename) { // disable caching $now = gmdate("D, ...

  2. maven的一些使用配置!

    1.国外库太慢,更换为国内镜像库在你的maven安装目录下找到conf目录下的setting.xml修改:<mirrors> <id>CN</id> <nam ...

  3. Oracle数据库存量数据抽取使用spool控制命令

    spool是oracle  sqlplus提供的一个控制命令.可以利用spool和select语句的组合动态生成一些失去了脚本或者一些数据. 1.spool作用: 在sqlplus中用来保存或打印查询 ...

  4. Python全栈工程师(递归函数、闭包)

    ParisGabriel            每天坚持手写  一天一篇  决定坚持几年 全栈工程师     Python人工智能从入门到精通 函数式编程: 是指用一系列函数解决问题 每一个函数完成细 ...

  5. UVa 11426 - GCD - Extreme (II) 转化+筛法生成欧拉函数表

    <训练指南>p.125 设f[n] = gcd(1, n) + gcd(2, n) + …… + gcd(n - 1, n); 则所求答案为S[n] = f[2]+f[3]+……+f[n] ...

  6. # Including Artificial Intelligence in a Routing ProtocolUsing Software Defined Networks

    Abstract: 问题:AI在路由协议上的应用仅适用于真实设备,尤其是无线传感器节点 The inclusion of artificial intelligence (AI) can improv ...

  7. Sockt编程(多线程)

    服务器端: package com.zeph.serverclient; import java.io.BufferedReader; import java.io.IOException; impo ...

  8. java链接数据库--Mysql

    /************************************************************************* > File Name: Mysql.jav ...

  9. vi - vim的一些遗忘点

    1. vi 供分为三种模式:一般模式.编辑模式和命令行模式.i / Esc + :wq :q :q! 使vi在一般模式与编辑模式中来回转换. /word 向下寻找一个名称为word的字符串: ?wor ...

  10. Class-dump

    What is class-dump? This is a command-line utility for examining the Objective-C runtime information ...