令 ai 表示从 i 到根的边的长度。对于每个点维护 disti 表示从根到 i 的路径, mindisti 表示 i 的子树中 distj+aj 的最小值。
然后对于询问 (u,v) 分类:
如果 u 是 v 的祖先,由于权值都是正整数,答案为 distv−distu 。
否则答案为 mindistu−distu+distv 。
dist 和 mindist 用 dfs 序+线段树维护就可以了。
#include
#include
#include
#include
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if(p1==p2){
p2=(p1=buf)+fread(buf,1,100000,stdin);
if(p1==p2)return EOF;
}
return *p1++;
}
inline void Read(int& x){
char c=nc();
for(;c<'0'||c>'9';c=nc());
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
#define N 200010
#define ll long long
struct Edge{
int f,t,nx,w;
}e[N<<1];
ll c[N<<2],p[N<<2],Pa[N],c2[N<<2];
int d[N],Top[N],Son[N],l[N],r[N],s[N],f[N],w[N],x,y,z;
int h[N],Num;
int i,j,k,n,m,Q,a[N],L;
inline void Dfs1(int x,int y){
d[x]=++y;l[x]=++Num;s[x]=1;w[Num]=x;
for(int i=h[x];i;i=e[i].nx){
Pa[e[i].t]=Pa[x]+e[i].w;
Dfs1(e[i].t,y);
s[x]+=s[e[i].t];
if(s[e[i].t]>s[Son[x]])Son[x]=e[i].t;
}
r[x]=Num;
}
inline void Dfs2(int x,int y){
Top[x]=y;
if(Son[x])Dfs2(Son[x],y);
for(int i=h[x];i;i=e[i].nx)
if(e[i].t!=Son[x])Dfs2(e[i].t,e[i].t);
}
inline ll Min(ll x,ll y){
return xinline void Up(int x){
c[x]=Min(c[x<<1],c[x<<1|1]);
}
inline void Down(int x){
if(p[x]){
c[x<<1]+=p[x];c2[x<<1]+=p[x];p[x<<1]+=p[x];
c[x<<1|1]+=p[x];c2[x<<1|1]+=p[x];p[x<<1|1]+=p[x];
p[x]=0;
}
}
inline void Update1(int x,int l,int r,int y,int z){
if(l==r){
c[x]+=z;
return;
}
Down(x);
int Mid=l+r>>1;
if(y<=Mid)Update1(x<<1,l,Mid,y,z);else Update1(x<<1|1,Mid+1,r,y,z);
Up(x);
}
inline void Update2(int x,int l,int r,int L,int R,int y){
if(l>R||rreturn;
if(l>=L&&r<=R){
c[x]+=y;c2[x]+=y;p[x]+=y;
return;
}
Down(x);
int Mid=l+r>>1;
Update2(x<<1,l,Mid,L,R,y);Update2(x<<1|1,Mid+1,r,L,R,y);
Up(x);
}
inline ll Query(int x,int l,int r,int L,int R){
if(l>R||rreturn 1e18;
if(l>=L&&r<=R)return c[x];
Down(x);
int Mid=l+r>>1;
return Min(Query(x<<1,l,Mid,L,R),Query(x<<1|1,Mid+1,r,L,R));
}
inline ll Query2(int x,int l,int r,int y){
if(l==r)return c2[x];
Down(x);
int Mid=l+r>>1;
if(y<=Mid)return Query2(x<<1,l,Mid,y);
return Query2(x<<1|1,Mid+1,r,y);
}
inline void Build(int x,int l,int r){
if(l==r){
c[x]=Pa[w[l]]+a[w[l]];
c2[x]=Pa[w[l]];
return;
}
int Mid=l+r>>1;
Build(x<<1,l,Mid);Build(x<<1|1,Mid+1,r);
Up(x);
}
inline int Lca(int x,int y){
while(Top[x]!=Top[y])
if(d[Top[x]]>d[Top[y]])x=f[Top[x]];else y=f[Top[y]];
return d[x]>d[y]?y:x;
}
int main(){
Read(n);Read(Q);
for(i=1;ifor(i=1;i1].f),Read(e[i+n-1].t),Read(a[e[i+n-1].f]);
Num=0;Dfs1(1,0);Dfs2(1,1);
Build(1,1,n);
while(Q--){
Read(k);Read(x);Read(y);
if(k==1){
if(x>=n)Update1(1,1,n,l[e[x].f],y-a[e[x].f]),a[e[x].f]=y;else
Update2(1,1,n,l[e[x].t],r[e[x].t],y-e[x].w),e[x].w=y;
}else{
L=Lca(x,y);
if(L==x)printf("%I64d\n",Query2(1,1,n,l[y])-Query2(1,1,n,l[x]));else
printf("%I64d\n",Query(1,1,n,l[x],r[x])-Query2(1,1,n,l[x])+Query2(1,1,n,l[y]));
}
}
return 0;
}