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静态文件返回304

    有时一些静态文件(如图片)会由php输出,会发现请求都是200,静态文件每次都去服务器上请求太浪费资源了,这时如何让浏览器缓存图片呢?就需要我们在php中输出304了. 我们可以利用php中的 HTT ...

  2. pychram 的一些小技巧

    1.如何添加头部注释代码 进入设置 File->Settings->Editor->File and Code Templeates -> Python Script 添加以下 ...

  3. 遍历列表,打印:我叫name,今年age岁,家住dizhi,电话phone(我是通过下标取键得到对应值,有哪位大神来个更简单的)

    lt = [ {'name':'小王', 'age':18, 'info':[('phone', '123'), ('dizhi', '广州')]}, {'name':'小芳', 'age':19, ...

  4. (原、整)BSP的江湖传说

    @author:黑袍小道 查看随缘,当苦无妨,良人可归.     引言 为什么叫江湖传说,因为实现了第一人是卡马克,就这么简单.(不接受那啥) Quake3:http://www.mralligato ...

  5. Win10 Ubuntu18.04 编译安装 nignx

    nginx 下载页 http://nginx.org/en/download.html wget http://nginx.org/download/nginx-1.14.0.tar.gz //安装依 ...

  6. 【bzoj4994】[Usaco2017 Feb]Why Did the Cow Cross the Road III 树状数组

    题目描述 给定长度为2N的序列,1~N各处现过2次,i第一次出现位置记为ai,第二次记为bi,求满足ai<aj<bi<bj的对数 样例输入 4 3 2 4 4 1 3 2 1 样例输 ...

  7. 【bzoj2565】最长双回文串 Manacher+树状数组

    原文地址:http://www.cnblogs.com/GXZlegend/p/6802558.html 题目描述 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc ...

  8. 【POJ3415】 Common Substrings (SA+单调栈)

    这道是求长度不小于 k 的公共子串的个数...很不幸,我又TLE了... 解法参考论文以及下面的链接 http://www.cnblogs.com/vongang/archive/2012/11/20 ...

  9. struts2的ajax支持

    struts2支持一种stream类型的Result,这种类型的Result可以直接向客户端浏览器响应二进制,文本等, 我们可以再action里面生成文本响应,然后在客户端页面动态加载该响应即可. 直 ...

  10. TCP面试题之四次挥手过程

    TCP四次挥手过程: 1.第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态: 2.第二次挥手:Server收到FIN后,发 ...