题目大意:给定一棵树,支持修改边权和查询两点距离。
显然可以链剖去做。但是注意到dis(x,y)=dis(1,x)+dis(1,y)-2*(dis(1,LCA(x,y)))。
然后修改到x的边的边权等价于让x子树中的所有点的dis(1,y)+=c。
然后显然可以用BIT维护。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define MAXN 100010
#define MAXM 200010
#define MAXL 21
#define lowbit(x) ((x)&(-(x)))
using namespace std;
struct edges{
int to,pre,wgt,id;
}e[MAXM];int out[MAXN];
int to[MAXN],h[MAXN],etop,d[MAXN];
int in[MAXN],times[MAXN],dfs_clock;
int up[MAXN][MAXL],dep[MAXN],w[MAXN];
int add_edge(int u,int v,int w,int id)
{
etop++;
e[etop].to=v;
e[etop].wgt=w;
e[etop].id=id;
e[etop].pre=h[u];
h[u]=etop;
return 0;
}
int dfs(int x,int f,int dis,int id)
{
times[in[x]=++dfs_clock]=x;d[x]=dis;
up[x][0]=f;dep[x]=dep[f]+1;to[id]=x;
for(int i=1;i<MAXL;i++)
up[x][i]=up[up[x][i-1]][i-1];
for(int i=h[x];i;i=e[i].pre)
if(e[i].to^f) dfs(e[i].to,x,dis+e[i].wgt,e[i].id);
out[x]=dfs_clock;return 0;
}
inline int getLCA(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
for(int i=MAXL-1;i>=0;i--)
if(dep[up[u][i]]>=dep[v])
u=up[u][i];
if(u==v) return u;
for(int i=MAXL-1;i>=0;i--)
if(up[u][i]!=up[v][i])
u=up[u][i],v=up[v][i];
return up[u][0];
}
struct segment{
int l,r,s,pt;
segment *ch[2];
}*rt,seg_pool[MAXN<<1];
queue<segment*> pool;
inline int push_up(segment* &rt)
{
return rt->s=rt->ch[0]->s+rt->ch[1]->s;
}
inline int update_tags(segment* &rt,int v)
{
rt->pt+=v;
rt->s+=(rt->r-rt->l+1)*v;
return 0;
}
inline int push_down(segment* &rt)
{
update_tags(rt->ch[0],rt->pt);
update_tags(rt->ch[1],rt->pt);
return rt->pt=0;
}
inline int build(segment* &rt,int l,int r)
{
// rt=pool.front();pool.pop();
rt=new segment;
rt->l=l,rt->r=r;rt->ch[0]=rt->ch[1]=NULL;
rt->s=rt->pt=0;
if(l==r) return rt->s=d[times[l]];
int mid=(l+r)>>1;
build(rt->ch[0],l,mid);
build(rt->ch[1],mid+1,r);
push_up(rt);return 0;
}
inline int update(segment* &rt,int s,int t,int v)
{
int l=rt->l,r=rt->r;
if(s<=l&&r<=t) return update_tags(rt,v);
if(rt->pt) push_down(rt);
int mid=(l+r)>>1;
if(s<=mid) update(rt->ch[0],s,t,v);
if(mid<t) update(rt->ch[1],s,t,v);
return push_up(rt);
}
inline int query(segment* &rt,int p)
{
int l=rt->l,r=rt->r;
if(l==r) return rt->s;
if(rt->pt) push_down(rt);
int mid=(l+r)>>1;
if(p<=mid) return query(rt->ch[0],p);
else return query(rt->ch[1],p);
}
inline int delseg(segment* &rt)
{
if(rt==NULL) return 0;
delseg(rt->ch[0]);
delseg(rt->ch[1]);
pool.push(rt);rt=NULL;
return 0;
}
int v[MAXN],n;
inline int update(int x,int val)
{
for(x;x<=n;x+=lowbit(x))
v[x]+=val;
return 0;
}
inline int query(int x)
{
int ans=0;
for(x;x;x-=lowbit(x))
ans+=v[x];
return ans;
}
int main()
{
int q,x;
// for(int i=0;i<(MAXN<<1);i++) pool.push(&seg_pool[i]);
while(scanf("%d%d%d",&n,&q,&x)!=EOF&&(n||q||x))
{
memset(h,0,sizeof(h));etop=0;
for(int i=1;i<n;i++)
{
int u,v;scanf("%d%d%d",&u,&v,&w[i]);
add_edge(u,v,w[i],i);
add_edge(v,u,w[i],i);
}
dfs_clock=0;
int root=1;dfs(root,0,0,0);
// build(rt,1,n);
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++) update(i,d[times[i]]-d[times[i-1]]);
while(q--)
{
int opt;scanf("%d",&opt);
if(!opt)
{
int y;scanf("%d",&y);
// printf("%d\n",query(rt,in[x])+query(rt,in[y])-(query(rt,in[getLCA(x,y)])<<1));
printf("%d\n",query(in[x])+query(in[y])-(query(in[getLCA(x,y)])<<1));
x=y;
}
else{
int id,c;scanf("%d%d",&id,&c);
// update(rt,in[to[id]],out[to[id]],c-w[id]);w[id]=c;
update(in[to[id]],c-w[id]);
update(out[to[id]]+1,w[id]-c);w[id]=c;
}
}
// delseg(rt);
}
return 0;
}