可解決在給定的樹上的路徑問題。
複雜度:O( log2n log_2n)
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100015, maxe=200015;int n,Q,fir[maxn],nxt[maxe],son[maxe],w[maxe],tot;int hvy[maxn],sz[maxn],d[maxn],pre[maxn],w_pre[maxn],top[maxn],pos[maxn];struct node{ int L,R,sum; };struct segment{ node seg[maxn*4]; void maintain(int p){ seg[p].sum=seg[p<<1].sum+seg[p<<1|1].sum; } void build(int p,int L,int R,int* Arr){ seg[p].L=L; seg[p].R=R; if(L==R){ seg[p].sum=*(Arr+L); return; } int mid=(L+R)>>1; build(p<<1,L,mid,Arr); build(p<<1|1,mid+1,R,Arr); maintain(p); } void Updata(int p,int pos,int val){ if(pos<seg[p].L||seg[p].R<pos) return; if(pos==seg[p].L&&seg[p].R==pos){ seg[p].sum=val; return; } Updata(p<<1,pos,val); Updata(p<<1|1,pos,val); maintain(p); } int Query(int p,int L,int R){ if(R<seg[p].L||seg[p].R<L) return 0; if(L<=seg[p].L&&seg[p].R<=R) return seg[p].sum; if(seg[p].L==seg[p].R) return 0; return Query(p<<1,L,R)+Query(p<<1|1,L,R); }} T;void dfs(int x){ sz[x]=1; hvy[x]=0; for(int j=fir[x];j;j=nxt[j]) if(son[j]!=pre[x]){ pre[son[j]]=x; d[son[j]]=d[x]+1; dfs(son[j]); sz[x]+=sz[son[j]]; if(sz[son[j]]>sz[hvy[x]]) hvy[x]=son[j]; } else w_pre[x]=w[j];}int c[maxn];void build_chain(int x,int tp){ top[x]=tp; c[++c[0]]=w_pre[x]; pos[x]=c[0]; if(hvy[x]) build_chain(hvy[x],tp); for(int j=fir[x];j;j=nxt[j]) if(son[j]!=pre[x]) if(son[j]!=hvy[x]) build_chain(son[j],son[j]);}int getsum(int x,int y){ int res=0; while(top[x]!=top[y]){ if(d[top[x]]<d[top[y]]) swap(x,y); res+=T.Query(1,pos[top[x]],pos[x]); x=pre[top[x]]; } if(x==y) return res; if(d[x]>d[y]) swap(x,y); return res+=T.Query(1,pos[x]+1,pos[y]);}void add(int x,int y,int z){ son[++tot]=y; w[tot]=z; nxt[tot]=fir[x]; fir[x]=tot;}struct edge{ int x,y; } e[maxe];int now;int main(){ freopen("poj2763.in","r",stdin); freopen("poj2763.out","w",stdout); scanf("%d%d%d",&n,&Q,&now); for(int i=1;i<=n-1;i++){ int z; scanf("%d%d%d",&e[i].x,&e[i].y,&z); add(e[i].x,e[i].y,z); add(e[i].y,e[i].x,z); } dfs(1); build_chain(1,1); T.build(1,1,c[0],c); while(Q--){ int pd; scanf("%d",&pd); if(!pd){ int t; scanf("%d",&t); printf("%d\n",getsum(now,t)); now=t; } else{ int id,val; scanf("%d%d",&id,&val); if(d[e[id].x]<d[e[id].y]) swap(e[id].x,e[id].y); T.Updata(1,pos[e[id].x],val); } } return 0;}