Description
Rayray现在在一棵有n个节点的树,现需要你按要求完成rayray给出的询问和修改操作。
询问操作,从当前点出发到目标点,rayray所需要的时间。执行完此操作后,rayray会跑去目标点。
修改操作:将rayray通过树上某条边的时间修改为w。
Input
第1行,3个整数n,q,s,分别表示树的节点个数,询问和修改操作的总数以及rayray在树上的起始点。
第2行到第n行,每行3个整数x,y,w,表示从x和y之间有一条边相连,w表示rayray通过这条边所要的时间。
接下来q行,每行先给出一个数c。
若c为0,代表询问操作,接下来会给出一个数d,代表目标点。
若c为1,代表修改操作,接下来会给出两个数i,w,代表把第i条边的时间修改为w。
Output
对于每个询问操作,输出一个整数(占一行),表示需要的时间。
Sample Input
3 3 1
1 2 1
2 3 2
0 2
1 2 3
0 3
Sample Output
1
3
Hint
数据范围
对于30%的数据,n,q<=1000;
对于100%的数据,n,q<=100000,1<=w<=10000。
做法很老,就是边权降点权,LCA,然后用什么数据结构维护一下点权的修改,ans就是dis[X]+dis[Y]-2*dis[LCA(X,Y)],虽然Oj上TLE了但是cena上AC了= =
LCA是用ST表做的,数据结构是线段树,最近不会写树状数组了= =当然树链剖分是可以徒手裸着做的= =
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<iomanip> #include<cstdlib> #define LL long long #define N 200005 using namespace std; struct edge { int num,w,y,next; }e[N*2]; int last[N],w[N],begin[N],end[N],times=0,bdfn[N]; int ls[N*4],rs[N*4],lazy[N*4]; int first[N],R[N*2],ver[N*2],dis[N],tot,f[N*2][20]; int n,m; LL read() { LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void add(int x,int y,int z,int k) { e[++tot].y=y;e[tot].next=last[x];e[tot].w=z;last[x]=tot;e[tot].num=k; e[++tot].y=x;e[tot].next=last[y];e[tot].w=z;last[y]=tot;e[tot].num=k; } void dfs(int x,int dep,int pre,int key) { begin[x]=++times; w[x]=key; ver[++tot]=x; first[x]=tot; R[tot]=dep; dis[x]=dis[pre]+key; for (int i=last[x];i!=0;i=e[i].next) if (e[i].y!=pre) { dfs(e[i].y,dep+1,x,e[i].w); ver[++tot]=x;R[tot]=dep;bdfn[e[i].num]=e[i].y; } end[x]=times; } int RMQ(int l,int r) { int k=0; while (1<<(k+1)<=r-l+1) k++; int x=f[l][k],y=f[r-(1<<k)+1][k]; return R[x]<R[y]?x:y; } int LCA(int x,int y) { int l=first[x],r=first[y]; if (l>r) swap(l,r); int res=RMQ(l,r); return ver[res]; } void DP(int n) { for (int i=1;i<=n;i++) f[i][0]=i; for (int j=1;(1<<j)<=n;j++) for (int i=1;i+(1<<j)-1<=n;i++) { int x=f[i][j-1],y=f[i+(1<<(j-1))][j-1]; f[i][j]=R[x]<R[y]?x:y; } } void build(int k,int l,int r) { if (l==r) { ls[k]=rs[k]=l; lazy[k]=0; return; } int mid=(l+r)>>1; build(k<<1,l,mid);build(k<<1|1,mid+1,r); ls[k]=l;rs[k]=r; } void motifiy(int k,int l,int r,int val) { if (ls[k]==l&&rs[k]==r) { lazy[k]+=val; return; } int mid=(ls[k]+rs[k])>>1; if (r<=mid) motifiy(k<<1,l,r,val); else { if (l>mid) motifiy(k<<1|1,l,r,val); else { motifiy(k<<1,l,mid,val);motifiy(k<<1|1,mid+1,r,val); } } } int query(int k,int x) { // cout<<ls[k]<<' '<<rs[k]<<endl; if (ls[k]==rs[k]) return lazy[k]; int mid=(ls[k]+rs[k])>>1; if (x>mid) return lazy[k]+query(k<<1|1,x); else return lazy[k]+query(k<<1,x); } int main() { freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); n=read();m=read();int lastans=read(); for (int i=1;i<n;i++) { int x=read(),y=read(),w=read(); add(x,y,w,i); } tot=0; dfs(1,1,0,0); DP(2*n-1); build(1,1,n); for (int i=1;i<=m;i++) { int ch=read(); // cout<<ch<<' '<<i<<endl; if (ch==0) { int x=read();int y=LCA(lastans,x); int ans=dis[lastans]+query(1,begin[lastans])+dis[x]+query(1,begin[x])-2*(dis[y]+query(1,begin[y])); // cout<<y<<' '<<lastans<<' '<<x<<endl; printf("%d\n",ans); lastans=x; } else { int x=read(),val=read();//if (i>70000) cout<<i<<' '<<end[bdfn[x]]<<' '<<w[bdfn[x]]<<endl; motifiy(1,begin[bdfn[x]],end[bdfn[x]],val-w[bdfn[x]]); w[bdfn[x]]=val; // cout<<"ok"<<endl; } } return 0; }