题目链接: http://poj.org/problem?id=2763
#include<stdio.h>
#include<string.h>
#include<math.h>
#define clr(x)memset(x,0,sizeof(x))
#define maxn 200005
struct node
{
int to,next,w,xu;
}e[];
int tot;
int head[maxn];
void add(int s,int t,int wi,int xu)
{
e[tot].xu=xu; //边的序号
e[tot].w=wi;
e[tot].to=t;
e[tot].next=head[s];
head[s]=tot++;
}
int dp[maxn<<][];
int x[maxn<<];
int d[maxn];
int r[maxn];
int v[maxn];
int f[maxn];
int ll[maxn];
int rr[maxn];
int g[maxn];
int n,m;
int min(int i,int j)
{
return d[i]<d[j]?i:j;
}
void makermq(int nn)
{
int i,j;
for(i=;i<nn;i++)
dp[i][]=i;
for(j=;(<<j)<=nn;j++)
for(i=;i+(<<j)-<nn;i++)
dp[i][j]=min(dp[i][j-],dp[i+(<<(j-))][j-]);
}
int rmq(int l,int r)
{
int k=(int)(log((r-l+)*1.0)/log(2.0));
return min(dp[l][k],dp[r-(<<k)+][k]);
}
int cnt,ti;
void dfs(int u,int deep)
{
v[u]=; //标记节点是否被访问;
x[cnt]=u; //cnt为标记访问点先后顺序的一个序列,x数组即表示当前访问的节点。
d[cnt]=deep; // d数组表示当前访问节点的深度。
r[u]=cnt++; // r 数组是表示本节点第一次出现在访问序列中的位置;
ll[u]=++ti; //第一次访问节点的时间戳
int i,k;
for(i=head[u];i;i=e[i].next)
{
k=e[i].to;
if(!v[k])
{
g[e[i].xu]=k;
dfs(k,deep+);
x[cnt]=u; //回退时也要记录访问序列;
d[cnt++]=deep;
}
}
rr[u]=ti; //第二次访问这个节点的时间戳
}
int tree[maxn];
int lowbit(int x)
{
return (x)&(-x);
}
void update(int pos,int x)
{
while(pos<=n)
{
tree[pos]+=x;
pos+=lowbit(pos);
}
}
int sum(int pos)
{
int s=;
while(pos>)
{
s+=tree[pos];
pos-=lowbit(pos);
}
return s;
}
int edge[maxn];
int val[maxn];
int main()
{
int i,st;
while(scanf("%d%d%d",&n,&m,&st)!=EOF)
{
int a,b,c;
clr(head); clr(v);
clr(f); clr(tree);
tot=;
ti=-;
for(i=;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
val[i]=c;
edge[i]=c;
add(a,b,c,i);
add(b,a,c,i);
}
cnt=;
dfs(,);
makermq(*n-);
for(i=;i<n;i++)
{
update(ll[g[i]],edge[i]);
update(rr[g[i]]+,-edge[i]);
}
int op;
while(m--)
{
scanf("%d",&op);
if(op==) //将树上的操作变成一个序列的操作。
{
scanf("%d%d",&a,&b);
update(ll[g[a]],-val[a]);
update(rr[g[a]]+,val[a]);
update(ll[g[a]],b);
update(rr[g[a]]+,-b);
val[a]=b;
}
else
{
scanf("%d",&a);
int lca,d1,d2,d3;
if(r[st]<=r[a])
lca=x[rmq(r[st],r[a])];
else lca=x[rmq(r[a],r[st])];
d1=sum(ll[st]);
d2=sum(ll[a]);
d3=sum(ll[lca]);
st=a;
printf("%d\n",d1+d2-*d3);
}
}
}
return ;
}

												

poj 2763 求树上的两个节点的最短距离+在线修改答案的更多相关文章

  1. LCA最近公共祖先模板(求树上任意两个节点的最短距离 || 求两个点的路进(有且只有唯一的一条))

    原理可以参考大神 LCA_Tarjan (离线) TarjanTarjan 算法求 LCA 的时间复杂度为 O(n+q) ,是一种离线算法,要用到并查集.(注:这里的复杂度其实应该不是 O(n+q)  ...

  2. poj 2763 Housewife Wind(树链剖分+单点查询+区间修改)

    题目链接:http://poj.org/problem?id=2763 题意:给一个数,边之间有权值,然后两种操作,第一种:求任意两点的权值和,第二,修改树上两点的权值. 题解:简单的树链剖分. #i ...

  3. poj 3608(旋转卡壳求解两凸包之间的最短距离)

    Bridge Across Islands Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9768   Accepted: ...

  4. Codeforces Round #588 (Div. 2)-E. Kamil and Making a Stream-求树上同一直径上两两节点之间gcd的和

    Codeforces Round #588 (Div. 2)-E. Kamil and Making a Stream-求树上同一直径上两两节点之间gcd的和 [Problem Description ...

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

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

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

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

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

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

  8. POJ 2763 Housewife Wind(DFS序+LCA+树状数组)

    Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 11419   Accepted: 3140 D ...

  9. 牛客小白月赛6 C 桃花 dfs 求树上最长直径

    链接:https://www.nowcoder.com/acm/contest/136/C来源:牛客网 题目描述 桃花一簇开无主,可爱深红映浅红.                            ...

随机推荐

  1. Access restriction required library rt.jar

    在JAVA项目开发中,使用到了BASE64Decoder,但编辑运行时却会出现以下错误:Access restriction required library rt.jar,这里就详细的说明一下如何解 ...

  2. URL网址参数解析类

    /** * Created by myc on 2015/12/9. */ import android.text.TextUtils; import java.util.HashMap; impor ...

  3. 修改 linux 时区时间和 php 时区

    问题:客户美国服务器时间不对第一步,先修改硬件时区. vim /etc/sysconfig/clock将 ZONE="America/New_York" 注释,加多一行 ZONE= ...

  4. oracle --(三)数据段(segment)

    基本关系:数据库---表空间---数据段---分区---数据块 数据段(segment)段(segment)由一系列的extent组成.通常一张表是一个segment. Oracle中的段可以分成4种 ...

  5. 开发工具 idea 激活方法

    1. 到网站 http://idea.lanyus.com/ 获取注册码. 2.填入下面的license server: http://intellij.mandroid.cn/ http://ide ...

  6. 百度Apollo解析——2.log系统

    Apollo中的glog 在Apollo中google glog 被广泛使用,glog 是 google 的一个 c++ 开源日志系统,轻巧灵活,入门简单,而且功能也比较完善. 1. 安装 以下是官方 ...

  7. __get(),__set(),__isset(),__unset()

    __get(),__set(),__isset(),__unset() 在给不可访问属性赋值时,__set()会被调用读取不可访问属性的值时,__get()会被调用 当对不可访问属性调用isset() ...

  8. C++字符串流保存数据

    文件流是以外存文件为输入输出对象的数据流.字符串流是以内存中用户定义的字符数组(字符串)为输入输出对象的. 建立输出字符串流: ostrstream strout(c,sizeof(c));第一个参数 ...

  9. C++对ASCII文件的操作例子

    从键盘读入一行字符,把其中的字母字符依次放在磁盘文件f2.dat中,再把它从磁盘文件读入程序,将其中的小写字母改写成大写字母,再存入磁盘文件f3.dat. code: #include<iost ...

  10. oracle环境变量配置

    1.右键我的电脑--->属性--->高级系统设置 2.环境变量---->新建 总共配置三个变量(1) 变量名 ORACLE_HOME 变量值 G:\app\TH\product\11 ...