//#include<bits/stdc++.h>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<iostream>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
using namespace std;
#define ll long long
#define pb push_back
const int maxn=1e6+7;
const int inf=0x3f3f3f3f;
struct EDGE{
int u,v,val,next;
}G[maxn<<1];
int tot;int head[maxn];
void init(){
memset(head,-1,sizeof head);tot=0;
}
void addedge(int u,int v,int w){
tot++;G[tot]={u,v,w,head[u]};head[u]=tot;
}
int vs[maxn<<1];
int in[maxn],out[maxn];
int tim;
int dep[maxn<<1];
int id[maxn];
int pre[maxn];
void dfs(int u,int fa,int d){
pre[u]=fa;
id[u]=++tim;vs[tim]=u;dep[tim]=d;
in[u]=tim;out[u]=tim;
for(int i=head[u];~i;i=G[i].next){
EDGE e=G[i];
if(e.v==fa)continue;
dfs(e.v,u,d+e.val);
vs[++tim]=u;dep[tim]=d;out[u]=tim;
}
}
struct node{
int fa; //区间内公共祖先
int mindep;
int add; //lazy
}ST[maxn<<2];
void pushdown(int rt){
if(ST[rt].add){
ST[rt<<1].mindep+=ST[rt].add;ST[rt<<1|1].mindep+=ST[rt].add;
ST[rt<<1].add+=ST[rt].add;ST[rt<<1|1].add+=ST[rt].add;
ST[rt].add=0;
}
}
void pushup(int rt){
if(ST[rt<<1].mindep<=ST[rt<<1|1].mindep){
ST[rt].mindep=ST[rt<<1].mindep;
ST[rt].fa=ST[rt<<1].fa;
}else{
ST[rt].mindep=ST[rt<<1|1].mindep;
ST[rt].fa=ST[rt<<1|1].fa;
}
}
void build(int l,int r,int rt){
if(l==r){
ST[rt].mindep=dep[l];
ST[rt].fa=vs[l];
ST[rt].add=0;
return;
}
ST[rt].add=0;
int m=l+r>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
pushup(rt);
}
void update(int a,int b,int c,int l,int r,int rt){
if(a<=l&&b>=r){
ST[rt].mindep+=c;
ST[rt].add+=c;
return;
}
pushdown(rt);
int m=l+r>>1;
if(a<=m)update(a,b,c,l,m,rt<<1);
if(b>m)update(a,b,c,m+1,r,rt<<1|1);
pushup(rt);
}
node query(int a,int b,int l,int r,int rt){ //查询a-b内的祖先
//cout<<a<<" "<<b<<" "<<l<<" "<<r<<endl;
if(a<=l&&b>=r){
return ST[rt];
}
pushdown(rt);
int m=l+r>>1;
node n2={0,inf,0},n1={0,inf,0};
if(a<=m)n1=query(a,b,l,m,rt<<1);
if(b> m)n2=query(a,b,m+1,r,rt<<1|1);
if(n1.mindep<n2.mindep){return n1;}
else return n2;
}
int main(){
int n,q,s;
while(~scanf("%d%d%d",&n,&q,&s)){
init();
for(int i=1;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
//if(u>v)swap(u,v);
addedge(u,v,w);
addedge(v,u,w);
}
int now=s;
tim=0;
dep[s]=0;
dfs(s,s,0);
build(1,tim,1);
for(int i=1;i<=q;i++){
int kind;int a,b;
scanf("%d",&kind);
if(kind){ //改边
scanf("%d%d",&a,&b);
a=2*a-1;
int flag=0;
if(pre[G[a].v]==G[a].u){flag=1;}
else a++;
EDGE e=G[a];
int plus=b-e.val;
update(in[e.v],out[e.v],plus,1,tim,1);
if(flag){
G[a].val=b;
G[a+1].val=b;
}else{
G[a].val=b;
G[a-1].val=b;
}
//for(int i=1;i<=tim;i++){
// cout<<vs[i]<<"ss"<<endl;
//}
}else{
scanf("%d",&a);
//cout<<now<<" "<<a<<endl;
node anc=
query(min(id[a],id[now]),max(id[now],id[a]),1,tim,1);
node n1,n2;
n1=query(id[now],id[now],1,tim,1);
n2=query(id[a],id[a],1,tim,1);
int ans=n1.mindep+n2.mindep-anc.mindep*2;
//cout<<n1.mindep<<" "<<n2.mindep<<" "<<anc.mindep<<endl;
//cout<<n1.fa<<" "<<n2.fa<<" "<<anc.fa<<endl;
printf("%d
",ans);
now=a;
}
}
}
}
/*
3 100 2
1 2 6
1 3 5
1 1 4
0 1
*/核心就是vs序列存下的in[u],out[u]的中间段只有u的子树
做法肯定不是最优的,因为检查每个节点的深度我都用到了线段树查询,慢了3倍
换上树状数组肯定能更快,但我懒得学。。
双向边的编号修改难死我了。。。还好想出办法解决了
(其实是别人的代码我看不懂