树链剖分(边)
将边权下放至两端点中深度大的点中,当做点权维护。
#include<iostream>
#include<algorithm>
using namespace std;
#define gc getchar
template<typename T>
inline void read(T&x) {
int flag=x=0;
char ch=gc();
while (ch<'0'||ch>'9')flag|=ch=='-',ch=gc();
while (ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-48,ch=gc();
if(flag)x=-x;
}
#define Init(arr,val) memset(arr,val,sizeof(arr))
#define lson (i<<1)
#define rson (i<<1|1)
#define mid ((l+r)>>1)
#define lowbit(x) ((x)&(-x))
const int inf=0x3f3f3f3f,MAXN=1e5+8;
struct E{int x,y,v,nt;}e[MAXN<<1];
int cnt,head[MAXN];
void add(int x,int y,int v){
e[++cnt].x=x;
e[cnt].y=y;
e[cnt].v=v;
e[cnt].nt=head[x];
head[x]=cnt;
}
int n,q,s;
int deep[MAXN],fa[MAXN],tot[MAXN],son[MAXN];
int to_son_val[MAXN];//某点与其重儿子的距离,便于与点权转换。
int dfs1(int now,int pre,int dep){
deep[now]=dep;fa[now]=pre;tot[now]=1;
int max_son=-1;
for(int i=head[now];i;i=e[i].nt){
int y=e[i].y;
if(y==pre)continue;
tot[now]+=dfs1(y,now,dep+1);
if(tot[y]>max_son)max_son=tot[y],son[now]=y,to_son_val[now]=e[i].v;
}return tot[now];
}
int top[MAXN],a[MAXN],id[MAXN],num;
void dfs2(int now,int topfa,int v){
//v;pre->now的距离。
id[now]=++num;
top[now]=topfa;
a[num]=v;
if(!son[now])return;
dfs2(son[now],topfa,to_son_val[now]);
for(int i=head[now];i;i=e[i].nt){
int y=e[i].y;
if(!id[y])dfs2(y,y,e[i].v);
}
}
int sum[MAXN<<2];
inline void up(int i){sum[i]=sum[lson]+sum[rson];}
void build(int i=1,int l=1,int r=n){
if(l==r){sum[i]=a[l];return;}
build(lson,l,mid);
build(rson,mid+1,r);
up(i);
}
void point_change(int p,int v,int i=1,int l=1,int r=n){
if(l==r){sum[i]=v;return;}
if(p<=mid)point_change(p,v,lson,l,mid);
else point_change(p,v,rson,mid+1,r);
up(i);
}
int interval_sum(int x,int y,int i=1,int l=1,int r=n){
if(x<=l&&r<=y)return sum[i];
int res=0;
if(x<=mid)res+=interval_sum(x,y,lson,l,mid);
if(y>mid)res+=interval_sum(x,y,rson,mid+1,r);
return res;
}
int path_sum(int x,int y){
//与点权类似,只是最后要减去点lca(x,y)的值。
int res=0;
while(top[x]^top[y]){
if(deep[top[x]]<deep[top[y]])swap(x,y);
res+=interval_sum(id[top[x]],id[x]);
x=fa[top[x]];
}
if(x^y){//相同的话说明只有lca点的权值没有加上。
if(deep[x]<deep[y])swap(x,y);
//y点即是lca,所以不用加上y点的值。
res+=interval_sum(id[y]+1,id[x]);
}
return res;
}
int main(){
read(n),read(q),read(s);
int x,y,v;
for(int i=1;i<n;++i){
read(x),read(y),read(v);
add(x,y,v),add(y,x,v);
}
dfs1(s,0,1);
dfs2(s,s,0);
build();
int op,i;
while(q--){
read(op);
if(op==1){
read(i),read(v);
x=e[i<<1].x,y=e[i<<1].y;
if(deep[x]>deep[y])point_change(id[x],v);
else point_change(id[y],v);
}else{
read(x);
printf("%d\n",path_sum(x,s));
s=x;
}
}
return 0;
}