http://poj.org/problem?id=2763

题意:给出 n 个点, n-1 条带权边, 询问是询问 s 到 v 的权值, 修改是修改存储时候的第 i 条边的权值。

思路:树链剖分之修改边权。边权的修改, 与点权修改不同的地方在于, 线段树中存的点是边,其中每条边边是以 儿子 的时间戳来记录的。例如: u -> v , dep[u] < dep[v], 说明 u 是 v 的父亲,所以这条边在线段树中的编号就是以 tid[v].

 #include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
#define N 100005
#define INF 0x3f3f3f3f
#define lson rt<<1, l, m
#define rson rt<<1|1, m+1, r
struct node
{
int v, w, next;
}edge[N*];
int head[N], tot;
int time, tid[N], fa[N], rak[N], son[N], dep[N], size[N], top[N];
int tree[N<<];
int e[N][]; /*
树链剖分: 边权的修改, 与点权修改不同的地方在于, 线段树中存的点是边,
其中每条边边是以 儿子 的时间戳来记录的
例如: u -> v , dep[u] < dep[v], 说明 u 是 v 的父亲,
所以这条边在线段树中的编号就是以 tid[v] 的形式来存储.
*/ void init()
{
memset(head, -, sizeof(head));
memset(son, -, sizeof(son));
memset(fa, , sizeof(fa));
time = tot = ;
} void add(int u, int v, int w)
{
edge[tot].next = head[u]; edge[tot].v = v; edge[tot].w = w; head[u] = tot++;
} void dfs1(int u, int f, int d)
{
size[u] = ;
dep[u] = d;
fa[u] = f;
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].v;
if(v == f) continue;
dfs1(v, u, d + );
size[u] += size[v];
if(son[u] == - || size[son[u]] < size[v])
son[u] = v;
}
} void dfs2(int u, int f)
{
tid[u] = ++time;
top[u] = f;
rak[time] = u;
if(son[u] == -) return ;
dfs2(son[u], f);
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].v;
if(v != son[u] && v != fa[u]) {
dfs2(v, v);
}
}
} void build(int rt, int l, int r)
{
tree[rt] = ;
if(l == r) return ;
int m = (l + r) >> ;
build(lson); build(rson);
} void pushup(int rt)
{
tree[rt] = tree[rt<<] + tree[rt<<|];
} void update(int rt, int l, int r, int id, int w)
{
if(l == id && r == id) {
tree[rt] = w;
return ;
}
if(l == r) return ;
int m = (l + r) >> ;
if(id <= m) update(lson, id, w);
else update(rson, id, w);
pushup(rt);
} long long query(int rt, int l, int r, int L, int R)
{
long long ans = ;
if(L <= l && r <= R) {
ans += tree[rt];
return ans;
}
int m = (l + r) >> ;
if(L <= m) ans += query(lson, L, R);
if(m < R) ans += query(rson, L, R);
return ans;
} long long change(int u, int v)
{
long long ans = ;
int tp1 = top[u], tp2 = top[v];
while(top[u] != top[v]) {
if(dep[top[u]] < dep[top[v]]) swap(u, v);
ans += query(, , time, tid[top[u]], tid[u]);
u = fa[top[u]];
}
if(dep[u] > dep[v]) swap(u, v);
if(u == v) return ans; // 如果是同一个点, 就不能继续询问了
ans += query(, , time, tid[son[u]], tid[v]);
return ans;
} int main()
{
int n, q, s;
scanf("%d%d%d", &n, &q, &s);
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;
add(u, v, w); add(v, u, w);
}
dfs1(s, s, );
dfs2(s, s);
build(, , time);
for(int i = ; i < n; i++) {
if(dep[e[i][]] > dep[e[i][]]) swap(e[i][], e[i][]);
update(, , time, tid[e[i][]], e[i][]);
}
for(int i = ; i < q; i++) {
int o, a, b;
scanf("%d", &o);
if(o == ) {
scanf("%d%d", &a, &b);
update(, , time, tid[e[a][]], b);
} else {
scanf("%d", &a);
long long ans = change(s, a);
s = a;
printf("%lld\n", ans);
}
}
return ;
} /*
4 4 1
1 2 1
2 3 2
1 4 1
0 2
1 2 3
0 3
0 4
*/

POJ 2763:Housewife Wind(树链剖分)的更多相关文章

  1. POJ - 2763 Housewife Wind (树链剖分/ LCA+RMQ+树状数组)

    题意:有一棵树,每条边给定初始权值.一个人从s点出发.支持两种操作:修改一条边的权值:求从当前位置到点u的最短路径. 分析:就是在边可以修改的情况下求树上最短路.如果不带修改的话,用RMQ预处理LCA ...

  2. POJ 2763 Housewife Wind (树链剖分 有修改单边权)

    题目链接:http://poj.org/problem?id=2763 n个节点的树上知道了每条边权,然后有两种操作:0操作是输出 当前节点到 x节点的最短距离,并移动到 x 节点位置:1操作是第i条 ...

  3. poj 2763 Housewife Wind : 树链剖分维护边 O(nlogn)建树 O((logn)²)修改与查询

    /** problem: http://poj.org/problem?id=2763 **/ #include<stdio.h> #include<stdlib.h> #in ...

  4. poj 2763 Housewife Wind(树链拆分)

    id=2763" target="_blank" style="">题目链接:poj 2763 Housewife Wind 题目大意:给定一棵 ...

  5. POJ 2763 Housewife Wind 树链拋分

    一.前言 这破题WA了一天,最后重构还是WA,最后通过POJ讨论版得到的数据显示,我看上去是把某个变量写错了..于是,还是低级错误背锅啊....代码能力有待进一步提升2333333 二.题意 某家庭主 ...

  6. POJ2763 Housewife Wind 树链剖分 边权

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

  7. poj 2763(RMQ+BIT\树链剖分)

    传送门:Problem 2763 https://www.cnblogs.com/violet-acmer/p/9686774.html 题意: 一对夫妇居住在xx村庄,小屋之间有双向可达的道路,不会 ...

  8. POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...

  9. POJ 2763 Housewife Wind LCA转RMQ+时间戳+线段树成段更新

    题目来源:POJ 2763 Housewife Wind 题意:给你一棵树 2种操作0 x 求当前点到x的最短路 然后当前的位置为x; 1 i x 将第i条边的权值置为x 思路:树上两点u, v距离为 ...

  10. poj 2763 Housewife Wind (树链剖分)

    题目链接:http://poj.org/problem?id=2763 题意: 给定一棵含n个结点的树和树的边权,共有q次操作,分为两种 0 c :求从位置s到c的距离,然后s变成c 1 a b:把第 ...

随机推荐

  1. 学习"大众点评网的架构设计与实践"

    今天看了一篇"程序员"上的文章:"大众点评网的架构与实践",因为里面谈的架构演变之路中所经历的痛点对我的工作经验来说感同身受,所以觉得文章里的一些解决方案对我还 ...

  2. AJAX POST&跨域 解决方案 - CORS(转载)

    跨域是我在日常面试中经常会问到的问题,这词在前端界出现的频率不低,主要原因还是由于安全限制(同源策略, 即JavaScript或Cookie只能访问同域下的内容),因为我们在日常的项目开发时会不可避免 ...

  3. 怎么查找执行比较慢的sql语句-DBA给的建议

    1.使用sql动态视图 如下: b.text,a.total_worker_time,a.total_logical_reads,a.total_elapsed_time,execution_coun ...

  4. leetcode-5 最长回文子串(动态规划)

    题目要求: * 给定字符串,求解最长回文子串 * 字符串最长为1000 * 存在独一无二的最长回文字符串 求解思路: * 回文字符串的子串也是回文,比如P[i,j](表示以i开始以j结束的子串)是回文 ...

  5. TIJ——Chapter One:Introduction to Objects

    ///:~容我对这个系列美其名曰"读书笔记",其实shi在练习英文哈:-) Introduction to Objects Object-oriented programming( ...

  6. Summary: Merge Sort of Array && 求逆序对

    常用算法(后面有inplace版本): package ArrayMergeSort; import java.util.Arrays; public class Solution { public ...

  7. C++如何通过一个响应事件接受多个控件消息

    在空的Form里加个Button,写入void __fastcall TForm1::Button1Click(TObject *Sender){ for (long k=0; k<5; k++ ...

  8. 20145207 《Java程序设计》第10周学习总结

    前言:   最后一篇java博客好激动啊..不过猜猜我在干什么?没错,安虚拟机,唉!紧接着又是一大波信安系统的博客,真开心~好啦边敲博客,边装虚拟机. 教材知识汇总 13.1 网络概述 13.1.1计 ...

  9. Linux 硬盘分区

    Linux系统中的重要概念,一切资源都看做是文件,包括硬件设备. 1. 基本概念 1)MBR:Master Boot Recorder,存放主引导记录,446字节的引导代码. 2)主分区表:存放主分区 ...

  10. 查看Linux服务器各种信息方法

    有的时候需要搜集服务器的各种信息,比如cpu信息,内存信息,linux版本信息,安装的各种软件信息等等.下面总结几种主要指标的查看方法. 1. 查看Linux发行版信息 [root@pcmweb ~] ...