给一棵N个节点的边上带权树,给一个起点,接下来有M个操作,0 i:从当前位置走到i点,并且输出路径和;1 i w:把第i条边的权值变成w。整体上思路还是dis[x]+dis[y]-2*dis[lca(x,y)],但是更新时如果一条一条的去更新,显然会超时..这里可以结合dfs序和树状数组来实现更新和查询。首先dfs的时候给各个节点重新编号打上时间戳,这样每个节点的子树都会是一个连续的区间,那么某条边被改变的时候,先找到这条边连接的深度较大的点x,x子树的其实加上c与当前边权的差值,x子树的结束点减掉这部分值,就实现了这个区间的更新。查询的时候求一下LCA(x,y),在bit里找出对应的三个值就行。注意更新边的时候不仅要修改bit里的值,还要把这条边的值修改...这里漏了一句话结果调了一下午.....
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef int ll;
const int maxn=250000;
const int POW=19;
int n,m;
struct BIT
{
ll dt[maxn];
void init()
{
memset(dt,0,sizeof dt);
}
int lowbit(int x)
{
return x&(-x);
}
void modify(int x,ll c)
{
if (x==0 || x>n) return;
for (int x1=x; x1<=n; x1+=lowbit(x1))
{
dt[x1]+=c;
}
}
ll query(int x)
{
ll res=0;
for (int x1=x; x1>0; x1-=lowbit(x1))
{
res+=dt[x1];
}
return res;
}
}bit;
struct EDGE
{
int f,v,w,next,id;
}edge[maxn<<2];
int g[maxn];
int d[maxn];
int p[maxn][20];
int dfsclock;
int l[maxn],r[maxn];
void dfs(int u,int fa)
{
l[u]=++dfsclock;
d[u]=d[fa]+1;
p[u][0]=fa;
for (int i=1; i<POW; i++) p[u][i]=p[p[u][i-1]][i-1];
for (int j=g[u]; j!=-1; j=edge[j].next)
{
int v=edge[j].v;
if (v==fa) continue;
dfs(v,u);
r[v]=dfsclock+1;
// dis[id[v]]=dis[id[u]]+edge[j].w;
bit.modify(l[v],edge[j].w);
bit.modify(r[v],-edge[j].w);
}
}
int lca(int a,int b)
{
if (d[a]>d[b]) swap(a,b);
if (d[a]<d[b])
{
int del=d[b]-d[a];
for (int i=0; i<POW; i++) if (del&(1<<i)) b=p[b][i];
}
if (a!=b)
{
for (int i=POW-1; i>=0; i--)
{
if (p[a][i]!=p[b][i])
a=p[a][i],b=p[b][i];
}
a=p[a][0];
b=p[b][0];
}
return a;
}
int s,k,x,y,z;
int cn;
int fr[maxn],to[maxn],w[maxn];
int main()
{
// freopen("in.txt","r",stdin);
while(~scanf("%d%d%d",&n,&m,&s))
{
bit.init();
memset(g,-1,sizeof g);
memset(p,0,sizeof p);
memset(d,0,sizeof d);
memset(l,0,sizeof l);
memset(r,0,sizeof r);
memset(fr,0,sizeof fr);
memset(to,0,sizeof to);
memset(w,0,sizeof w);
cn=0;
dfsclock=0;
for (int i=1; i<n; i++)
{
scanf("%d%d%d",&fr[i],&to[i],&z);
x=fr[i];
y=to[i];
w[i]=z;
edge[cn].v=y;
edge[cn].w=z;
edge[cn].next=g[x];
g[x]=cn;
cn++;
edge[cn].v=x;
edge[cn].w=z;
edge[cn].next=g[y];
g[y]=cn;
cn++;
}
dfs(1,-1);
for (int i=1; i<=m; i++)
{
scanf("%d",&x);
if (x==0)
{
scanf("%d",&y);
z=lca(s,y);
ll aa,bb,cc;
aa=bit.query(l[s]);
bb=bit.query(l[y]);
cc=(bit.query(l[z])<<1);
cout<<aa+bb-cc<<endl;
s=y;
}
else
{
scanf("%d%d",&y,&z);
int t;
if (d[fr[y]]>d[to[y]]) t=fr[y];
else t=to[y];
bit.modify(l[t],z-w[y]);
bit.modify(r[t],w[y]-z);
w[y]=z;
}
}
}
return 0;
}