#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define MEM(a,b) memset(a,b,sizeof(a));
int n,m,s;
const int maxn=100010;
struct Node{
int u,v,w,next;
}e[maxn],edge[2*maxn];
int cnt;
int head[maxn];
//记siz[v]表示以v为根的子树的节点数,dep[v]表示v的深度(根深度为1),top[v]表示v所在的链的
//顶端节点,fa[v]表示v的父亲,son[v]表示与v在同一重链上的v的儿子节点(姑且称为重儿子),
//id[v]表示v与其父亲节点的连边(姑且称为v的父边)在线段树中的位置。
int dep[maxn],siz[maxn],son[maxn],fa[maxn];
int top[maxn],id[maxn];top 最近的重链父节点
int num;
void addedge(int u,int v){
edge[cnt].u=u;edge[cnt].v=v;edge[cnt].next=head[u]++;head[u]=cnt++;
}
void dfs1(int u,int f,int d){
dep[u]=d;
siz[u]=1;
son[u]=0;
fa[u]=f;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==f)continue;
dfs1(v,u,d+1);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v])
son[u]=v;
}
}
void dfs2(int u,int tp){
top[u]=tp;
id[u]=++num;
if(son[u])dfs2(son[u],tp);
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
}
struct Tree{
int l,r,val;
}tree[4*maxn];
#define lson 2*o,l,mid
#define rson 2*o+1,mid+1,r
int Val[maxn];
void pushup(int x){
tree[x].val=tree[2*x].val+tree[2*x+1].val;
}
void build(int o,int l,int r){//建树一致
tree[o].l=l;tree[o].r=r;
if(l==r){
tree[o].val=Val[l];
return;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
pushup(o);
}
void update(int o,int a,int b){//更新操作一致
if(tree[o].l==tree[o].r){
tree[o].val=b;
return;
}
int mid=(tree[o].l+tree[o].r)>>1;
if(a<=mid)
update(2*o,a,b);
else
update(2*o+1,a,b);
pushup(o);
}
int query(int o,int l,int r){
if(tree[o].l>=l&&tree[o].r<=r){
return tree[o].val;
}
int mid=(tree[o].l+tree[o].r)>>1;
if(r<=mid)
return query(2*o,l,r);
else if(l>mid)
return query(2*o+1,l,r);
else
return query(lson)+query(rson);
}
int find(int u,int v){
int tp1=top[u],tp2=top[v];
int ans=0;
while(tp1!=tp2){
if(dep[tp1]<dep[tp2]){
swap(tp1,tp2);
swap(u,v);
}
ans+=query(1,id[tp1],id[u]);
u=fa[tp1];
tp1=top[u];
}
if(u==v)return ans;
if(dep[u]>dep[v])swap(u,v);
ans+=query(1,id[son[u]],id[v]);
return ans;
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
cnt=0;num=0;
MEM(head,-1);
for(int i=1;i<n;i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
addedge(e[i].u,e[i].v);
addedge(e[i].v,e[i].u);
}
dfs1(1,0,1);
dfs2(1,1);
for(int i=1;i<n;i++){
if(dep[e[i].u]<dep[e[i].v])
std::swap(e[i].u,e[i].v);
Val[id[e[i].u]]=e[i].w;
}
build(1,1,num);
for(int i=0;i<m;i++){
int ok,x,y;
scanf("%d",&ok);
if(ok==0){
scanf("%d",&x);
printf("%d\n",find(s,x));
s=x;
}
else{
scanf("%d%d",&x,&y);
update(1,id[e[x].u],y);
}
}
return 0;
}
图论之树链剖分模板
最新推荐文章于 2022-08-18 15:25:51 发布