POJ 2763 /// 基于边权的树链剖分
题目大意:
给定n个结点,有n-1条无向边,给定每条边的边权
两种操作,第一种:求任意两点之间路径的权值和,第二种:修改树上一点的权值。
因为是一棵树,可以直接把 u点和v点间(假设u为父节点,v为子节点)的边 的边权往下给v点
这样就转换成了点权,那么此时查询 u点到v点之间路径的权值和 的话
由于u点存有 u的父节点到u 的边权,所以应该查询的是 u到v的路径上 的第二个点到v的权值和
修改查询树上两结点间路径长度的函数
int queryPath(int x,int y){ }
中求最后一步的部分 /// 点权版本
if(p[x]>p[y]) swap(x,y);
return ans+query(p[x],p[y],,pos,);
/// 边权版本
if(x==y) return ans;
if(dep[x]>dep[y]) swap(x,y);
return ans+query(p[son[x]],p[y],root);
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define mem(i,j) memset(i,j,sizeof(i))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define root 1,n,1 const int maxn=1e5+;
int n,q,s; struct QTree {
struct EDGE { int to,ne; }e[maxn<<];
int head[maxn], tot;
void add(int u,int v) {
e[tot].to=v;
e[tot].ne=head[u];
head[u]=tot++;
} int fa[maxn], son[maxn], dep[maxn], num[maxn];
int top[maxn], p[maxn], fp[maxn], pos; int sumT[maxn<<]; void init() {
tot=; mem(head,);
pos=; mem(son,);
} // --------------------以下是线段树------------------------- void pushup(int rt) {
sumT[rt]=sumT[rt<<]+sumT[rt<<|];
}
void build(int l,int r,int rt) {
if(l==r) {
sumT[rt]=; return ;
}
int m=(l+r)>>;
build(lson), build(rson);
pushup(rt);
}
void update(int k,int w,int l,int r,int rt) {
if(l==r) {
sumT[rt]=w; return;
}
int m=(l+r)>>;
if(k<=m) update(k,w,lson);
else update(k,w,rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt) {
if(L<=l && r<=R) return sumT[rt];
int m=(l+r)>>, res=;
if(L<=m) res+=query(L,R,lson);
if(R>m) res+=query(L,R,rson);
return res;
} // --------------------以上是线段树------------------------- // --------------------以下是树链剖分------------------------- void dfs1(int u,int pre,int d) {
dep[u]=d; fa[u]=pre; num[u]=;
for(int i=head[u];i;i=e[i].ne) {
int v=e[i].to;
if(v!=fa[u]) {
dfs1(v,u,d+);
num[u]+=num[v];
if(!son[u] || num[v]>num[son[u]])
son[u]=v;
}
}
}
void dfs2(int u,int sp) {
top[u]=sp; p[u]=++pos; fp[p[u]]=u;
if(!son[u]) return;
dfs2(son[u],sp);
for(int i=head[u];i;i=e[i].ne) {
int v=e[i].to;
if(v!=son[u] && v!=fa[u])
dfs2(v,v);
}
}
int queryPath(int x,int y) {
int ans=;
int fx=top[x], fy=top[y];
while(fx!=fy) {
if(dep[fx]>=dep[fy]) {
ans+=query(p[fx],p[x],root);
x=fa[fx];
} else {
ans+=query(p[fy],p[y],root);
y=fa[fy];
}
fx=top[x], fy=top[y];
}
if(x==y) return ans;
if(dep[x]>dep[y]) swap(x,y);
return ans+query(p[son[x]],p[y],root);
} // --------------------以上是树链剖分------------------------- void initQTree() {
dfs1(,,);
dfs2(,);
build(root);
}
}T;
int E[maxn][]; int main()
{
while(~scanf("%d%d%d",&n,&q,&s)) {
T.init();
for(int i=;i<n;i++) {
int u,v,w; scanf("%d%d%d",&u,&v,&w);
E[i][]=u, E[i][]=v, E[i][]=w;
T.add(u,v); T.add(v,u);
}
T.initQTree();
for(int i=;i<n;i++) {
if(T.dep[E[i][]]>T.dep[E[i][]])
swap(E[i][],E[i][]);
T.update(T.p[E[i][]],E[i][],root);
}
while(q--) {
int op; scanf("%d",&op);
if(op) {
int k,w; scanf("%d%d",&k,&w);
T.update(T.p[E[k][]],w,root);
} else {
int v; scanf("%d",&v);
printf("%d\n",T.queryPath(s,v));
s=v;
}
}
} return ;
}
POJ 2763 /// 基于边权的树链剖分的更多相关文章
- POJ 2763:Housewife Wind(树链剖分)
http://poj.org/problem?id=2763 题意:给出 n 个点, n-1 条带权边, 询问是询问 s 到 v 的权值, 修改是修改存储时候的第 i 条边的权值. 思路:树链剖分之修 ...
- HDU 3966 & POJ 3237 & HYSBZ 2243 & HRBUST 2064 树链剖分
树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...
- fzu 2082 过路费 (树链剖分+线段树 边权)
Problem 2082 过路费 Accept: 887 Submit: 2881Time Limit: 1000 mSec Memory Limit : 32768 KB Proble ...
- BZOJ 2157 旅行(树链剖分码农题)
写了5KB,1发AC... 题意:给出一颗树,支持5种操作. 1.修改某条边的权值.2.将u到v的经过的边的权值取负.3.求u到v的经过的边的权值总和.4.求u到v的经过的边的权值最大值.5.求u到v ...
- POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )
POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...
- HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分
树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...
- POJ 3237 Tree (树链剖分)
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 2825 Accepted: 769 Description ...
- 【BZOJ-4353】Play with tree 树链剖分
4353: Play with tree Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 31 Solved: 19[Submit][Status][ ...
- Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)
Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...
随机推荐
- sublime text3配置c++环境和一些插件
目录 Sublime Text 3是一个轻量级文本编辑器 下载sublime text 3: 安装MinGW 配置环境变量 win下行编译运行C/C++文件 Build你的C++System~ 快捷键 ...
- 剑指offer---1、顺时针打印矩阵
剑指offer---1.顺时针打印矩阵 一.总结 一句话总结: 谋而后动+多做:还是要谋而后动,但是怎么谋而后动,很有学问,做好的方式就是多做 问题就这些问题:解决了就好了,比如php多维数组 面试的 ...
- Linux两台机器简历信任
cd ~/.ssh ssh-keygen -t rsa scp ./id_rsa.pub root@192.168.1.1:/root/.ssh/authorized_keys
- cut 从/a/b/c/d/e获取/a/b/c
https://www.cnblogs.com/chenxiaomeng/p/10066821.html two_dir=`echo /a/b/c/d/e/f | cut -d"/" ...
- Django(十四)课程机构列表页数据展示,Django的modelform,关于urls的重新分发
关于urls的重新分发: 如果所有url都配置在根路径的urls.py里,会特别多,而且也不易于修改,Django框架里支持urls的重新分发: 1.在根路径的urls配置上: PS:namespac ...
- zipinfo - 列出关于某个ZIP压缩包的详细信息
总览 SYNOPSIS zipinfo [-12smlvhMtTz] file[.zip] [file(s) ...] [-x xfile(s) ...] unzip -Z [-12smlvhMtTz ...
- linux常用命令-2网络相关命令
1.ip [选项] 操作对象{link|addr|route...} ip addr show #显示网卡IP信息 2.修改IP配置 1) root权限 2) cd /etc/sy ...
- line-height 行高的使用
line-height:normal; 默认 字体 line-height:1.5; line-height:200%; line-height:50px; ps : 固定的值 line-heig ...
- 转载-------- JSON 与 对象 、集合 之间的转换 JSON字符串和java对象的互转【json-lib】
转载--*--*---- 在开发过程中,经常需要和别的系统交换数据,数据交换的格式有XML.JSON等,JSON作为一个轻量级的数据格式比xml效率要高,XML需要很多的标签,这无疑占据了网络流量,J ...
- Linux统计根分区使用率
#!/bin/bash # 统计根分区使用率 # 作者: shaohsiung # 时间: // rate=$(df -h | grep "dev/sda3" | awk '{pr ...