给一棵N个节点的边上带权树,给一个起点,接下来有M个操作,0 i:从当前位置走到i点,并且输出路径和;1 i w:把第i条边的权值变成w。整体上思路还是dis[x]+dis[y]-2*dis[lca(x,y)],但是更新时如果一条一条的去更新,显然会超时..这里可以结合dfs序和树状数组来实现更新和查询。首先dfs的时候给各个节点重新编号打上时间戳,这样每个节点的子树都会是一个连续的区间,那么某条边被改变的时候,先找到这条边连接的深度较大的点x,x子树的其实加上c与当前边权的差值,x子树的结束点减掉这部分值,就实现了这个区间的更新。查询的时候求一下LCA(x,y),在bit里找出对应的三个值就行。注意更新边的时候不仅要修改bit里的值,还要把这条边的值修改...这里漏了一句话结果调了一下午.....
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> using namespace std; typedef int ll; const int maxn=250000; const int POW=19; int n,m; struct BIT { ll dt[maxn]; void init() { memset(dt,0,sizeof dt); } int lowbit(int x) { return x&(-x); } void modify(int x,ll c) { if (x==0 || x>n) return; for (int x1=x; x1<=n; x1+=lowbit(x1)) { dt[x1]+=c; } } ll query(int x) { ll res=0; for (int x1=x; x1>0; x1-=lowbit(x1)) { res+=dt[x1]; } return res; } }bit; struct EDGE { int f,v,w,next,id; }edge[maxn<<2]; int g[maxn]; int d[maxn]; int p[maxn][20]; int dfsclock; int l[maxn],r[maxn]; void dfs(int u,int fa) { l[u]=++dfsclock; d[u]=d[fa]+1; p[u][0]=fa; for (int i=1; i<POW; i++) p[u][i]=p[p[u][i-1]][i-1]; for (int j=g[u]; j!=-1; j=edge[j].next) { int v=edge[j].v; if (v==fa) continue; dfs(v,u); r[v]=dfsclock+1; // dis[id[v]]=dis[id[u]]+edge[j].w; bit.modify(l[v],edge[j].w); bit.modify(r[v],-edge[j].w); } } int lca(int a,int b) { if (d[a]>d[b]) swap(a,b); if (d[a]<d[b]) { int del=d[b]-d[a]; for (int i=0; i<POW; i++) if (del&(1<<i)) b=p[b][i]; } if (a!=b) { for (int i=POW-1; i>=0; i--) { if (p[a][i]!=p[b][i]) a=p[a][i],b=p[b][i]; } a=p[a][0]; b=p[b][0]; } return a; } int s,k,x,y,z; int cn; int fr[maxn],to[maxn],w[maxn]; int main() { // freopen("in.txt","r",stdin); while(~scanf("%d%d%d",&n,&m,&s)) { bit.init(); memset(g,-1,sizeof g); memset(p,0,sizeof p); memset(d,0,sizeof d); memset(l,0,sizeof l); memset(r,0,sizeof r); memset(fr,0,sizeof fr); memset(to,0,sizeof to); memset(w,0,sizeof w); cn=0; dfsclock=0; for (int i=1; i<n; i++) { scanf("%d%d%d",&fr[i],&to[i],&z); x=fr[i]; y=to[i]; w[i]=z; edge[cn].v=y; edge[cn].w=z; edge[cn].next=g[x]; g[x]=cn; cn++; edge[cn].v=x; edge[cn].w=z; edge[cn].next=g[y]; g[y]=cn; cn++; } dfs(1,-1); for (int i=1; i<=m; i++) { scanf("%d",&x); if (x==0) { scanf("%d",&y); z=lca(s,y); ll aa,bb,cc; aa=bit.query(l[s]); bb=bit.query(l[y]); cc=(bit.query(l[z])<<1); cout<<aa+bb-cc<<endl; s=y; } else { scanf("%d%d",&y,&z); int t; if (d[fr[y]]>d[to[y]]) t=fr[y]; else t=to[y]; bit.modify(l[t],z-w[y]); bit.modify(r[t],w[y]-z); w[y]=z; } } } return 0; }