题意: 知道了一颗有  n 个节点的树和树上每条边的权值,对应两种操作:

0 x        输出 当前节点到 x节点的最短距离,并移动到 x 节点位置

1 x val   把第 x 条边的权值改为 val

题意: 知道了一颗有  n 个节点的树和树上每条边的权值,对应两种操作:

0 x        输出 当前节点到 x节点的最短距离,并移动到 x 节点位置

1 x val   把第 x 条边的权值改为 val

LCA +RMQ+树状数组

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm> using namespace std; const int maxn = 2e5+; int N,Q,S;
//vector <int> G[maxn]; struct edge{
int to,next,w;
}e[*maxn]; int head[*maxn],tot;
void add_edge(int u,int v,int w)
{
e[tot].to = v;
e[tot].w = w;
e[tot].next = head[u];
head[u] = tot++; e[tot].to = u;
e[tot].w = w;
e[tot].next = head[v];
head[v] = tot++;
} int in[maxn],out[maxn],P[*maxn],fa[maxn][],dep[maxn],dis[maxn],cnt;
void dfs(int u,int _fa,int _dep,int _dis)
{
in[u] = ++cnt;
P[cnt] = u;
fa[u][] = _fa;
dis[u] = _dis;
dep[u] = _dep;
for(int i=head[u];~i;i=e[i].next)
{
int v = e[i].to;
if(v == _fa) continue;
dfs(v,u,_dep+,_dis+e[i].w);
}
out[u] = ++cnt;
}
void debug()
{
printf("in:\t");for(int i=;i<=N;i++) printf("%d ",in[i]);puts("");
printf("out:\t");for(int i=;i<=N;i++) printf("%d ",out[i]);puts("");
printf("p:\t");for(int i=;i<=cnt;i++) printf("%d ",P[i]);puts("");
printf("dis:\t");for(int i=;i<=N;i++) printf("%d ",dis[i]);puts("");
printf("dep:\t");for(int i=;i<=N;i++) printf("%d ",dep[i]);puts("");
printf("edge:");for(int i=;i<tot;i++) printf("\tto:%d w:%d\n",e[i].to,e[i].w);
} int initLCA()
{
int m = (int)log(N)/log()+;
for(int k=;k<m;k++)
{
for(int v=;v<=N;v++)
{
if(fa[v][k] < ) {fa[v][k+] = -;continue;}
else fa[v][k+] = fa[fa[v][k]][k];
}
}
} int LCA(int u,int v)
{
int m = (int)log(N)/log()+;
if(dep[v] > dep[u]) swap(u,v);
for(int k=;k<m;k++)
{
if((dep[u]-dep[v])>>k & )
u = fa[u][k];
}
if(u == v) return u;
for(int k=m-;k>=;k--)
{
if(fa[u][k] != fa[v][k])
{
u = fa[u][k];
v = fa[v][k];
}
}
return fa[u][];
} int c[*maxn];
int lowbit(int x) {return x&-x;} void init()
{
memset(head,-,sizeof head);
memset(fa,-,sizeof fa);
memset(c,,sizeof c);
memset(in,,sizeof in);
memset(out,,sizeof out);
tot = ;
cnt = ;
} void add(int x,int d)
{
while(x)
{
c[x] += d;
x -= lowbit(x);
}
}
void add_seg(int l,int r,int d)
{
add(r,d);
add(l-,-d);
}
int sum(int x)
{
int res = ;
//printf("u:%d ",P[x]);
while(x <= cnt)
{
res += c[x];
x += lowbit(x);
}
//printf("res:%d\n",res);
return res;
}
int dist(int x)
{
if(x == -) return ;
return sum(in[x]) + dis[x];
}
int main()
{
//freopen("input.txt","r",stdin);
while(~scanf("%d%d%d",&N,&Q,&S))
{
init();
for(int i=,u,v,w;i<N-;i++)
{
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
}
dfs(,-,,);
//debug();
initLCA();
for(int i=;i<tot;i+=)
{
if(dep[e[i].to] < dep[e[i+].to]) swap(e[i].to,e[i+].to);
}
int op;
for(int i=,a,b,c;i<Q;i++)
{
scanf("%d",&op);
if(op == )
{
scanf("%d",&a);
int lca = LCA(S,a);
//printf("lca:%d\n",lca); printf("%d\n",dist(S)+dist(a)-*(dist(lca)));
S = a;
}else
{
scanf("%d%d",&a,&b);
a--;
int u = e[a*].to;
int dw = b - (dist(u) - dist(fa[u][]));
//printf("dw:%d u:%d\n",dw,u);
add_seg(in[u],out[u],dw);
}
}
}
}

树链部分

#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 + ;
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] = ; son[u] = ;
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] + ;
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 << ] + sum[rt << | ];
}
void build(int l, int r, int rt) {
sum[rt] = ;
if(l == r) return;
int m = (l + r) / ;
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) / ;
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) / ;
ll res = ;
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, , n, );
else update(w[e[v].v], c, , n, );
}
ll seek(int v, int u) {
int t1 = top[v], t2 = top[u];
ll res = ;
while(t1 != t2) {
if(dep[t1] < dep[t2]) {
swap(t1, t2); swap(v, u);
}
res += query(w[t1], w[v], , n, );
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], , n, );
}
int main() {
memset(head, -, sizeof head);
cnt = num = ;
scanf("%d%d%d", &n, &q, &s);
for(int i = ; 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();
build_tree(, );
build(, n, );
for(int i = ; i < n; i++) {
if(dep[e[i].u] > dep[e[i].v]) update(w[e[i].u], e[i].c, , n, );
else update(w[e[i].v], e[i].c, , n, );
}
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 ;
}

POJ 2763 (LCA +RMQ+树状数组 || 树链部分) 查询两点距离+修改边权的更多相关文章

  1. 洛谷P3250 [HNOI2016]网络(整体二分+树状数组+树剖)

    传送门 据说正解是树剖套堆???然而代码看着稍微有那么一点点长…… 考虑一下整体二分,设当前二分到的答案为$mid$,如果所有大于$mid$的边都经过当前点$x$,那么此时$x$的答案必定小于等于$m ...

  2. 模拟赛 T3 DFS序+树状数组+树链的并+点权/边权技巧

    题意:给定一颗树,有 $m$ 次操作. 操作 0 :向集合 $S$ 中加入一条路径 $(p,q)$,权值为 $v$ 操作 1 :给定一个点集 $T$,求 $T$ 的并集与 $S$ 中路径含交集的权和. ...

  3. HDU 4031 Attack(线段树/树状数组区间更新单点查询+暴力)

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Sub ...

  4. NBOJv2 1050 Just Go(线段树/树状数组区间更新单点查询)

    Problem 1050: Just Go Time Limits:  3000 MS   Memory Limits:  65536 KB 64-bit interger IO format:  % ...

  5. UOJ#291. 【ZJOI2017】树状数组 树套树

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ291.html 题解 结论:这个写错的树状数组支持的是后缀加和后缀求和.这里的后缀求和在 x = 0 的时 ...

  6. hdu1556 树状数组区间更新单点查询板子

    就是裸的区间更新: 相对于直观的线段树的区间更新,树状数组的区间更新原理不太相同:由于数组中的一个结点控制的是一块区间,当遇到更新[l,r]时,先将所有能控制到 l 的结点给更新了,这样一来就是一下子 ...

  7. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  8. 【poj2155】Matrix(二维树状数组区间更新+单点查询)

    Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the ...

  9. hdu-3584 Cube---三维树状数组+区域更新单点查询

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3584 题目大意: 给定一个N*N*N多维数据集A,其元素是0或是1.A[i,j,k]表示集合中第 i ...

随机推荐

  1. 线程dump

    当应用程序运行变慢或者发生故障时,可能通过分析java的Thread Dumps得到分析他们得到阻塞和存在瓶颈的线程. 线程堆栈是虚拟机中线程(包括锁)状态的一个瞬间状态的快照,即系统在某一个时刻所有 ...

  2. Java-Http

    1 import java.io.BufferedReader; 2 import java.io.BufferedWriter; 3 import java.io.IOException; 4 im ...

  3. ubuntu16.04 Mask_RCNN AlphaPose OpenPose Librealsense

    #############MaskRCNNcource activate flappbirdcd /home/luo/Desktop/MyFile/MaskRCNN/MyOwnMaskRCNN1/sa ...

  4. 数字图像处理实验(17):PROJECT 06-04,Color Image Segmentation 标签: 图像处理MATLAB 2017-05-27 21:13

    实验报告: Objective: Color image segmentation is a big issue in image processing. This students need to ...

  5. logistic growth model . 求解方法 (高斯牛顿法)

    https://www.stat.tamu.edu/~jnewton/604/chap4.pdf http://www.metla.fi/silvafennica/full/sf33/sf334327 ...

  6. Python基础-3

    目录 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 知识插入:嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 一.函数基本语法 函数是什么? 函数一词 ...

  7. 函数有一个特殊的属性 prototype!

    JavaScript 中只有对象,没有类. 实际上,JavaScript 才是真正应该被称为「面向对象」的语言,因为它是少有的可以不通过类,直接创建对象的语言. 函数的 prototype 属性 在 ...

  8. [GO]结构体及普通变量初始化

    结构体是一种聚合的数据类型,它是由一系列相同类型或者不同类型的数据构成的数据集合,每个数据称为结构体的成员 1.结构体的初始化 package main import "fmt" ...

  9. Requests接口测试(三)

    一.定制请求头 我们先来看一下,关于请求头的定制演示,相信了解http协议的小伙伴应该对请求头部headers请求头部并不陌生,那么作为实际工作中的我们,如果想自定义一些请求头的信息,我们应该怎么办呢 ...

  10. Linq学习<一>

    lambda查询语法: var result =arrarylist.where(n=>n.contains("l"))  简化的委托方法实例 linq查询结构: var  ...