Qtree 1
这题要用到树链剖分
把边权变为其dep比较深的那个点的点权,然后树剖(注意LCA的权值是不能算进去的。)
//第一次树剖套线段树,以前都是套树状数组的。
#include<bits/stdc++.h> #define sight(c) ('0'<=c&&c<='9') using namespace std; #define N 100017 #define Mid (l+r>>1) #define eho(x) for(int i=head[x];i;i=net[i]) int fall[N<<1],net[N<<1],cost[N<<1],head[N],f[N],dep[N],siz[N],son[N]; int ma[N<<2],tot,n,co[N],id[N],tim,tp[N],ans,x,y,w,be[N],df[N]; char ch[47]; inline void read(int &x){ static char c;static int b; for (b=1,c=getchar();!sight(c);c=getchar())if(c=='-')b=-1; for (x=0;sight(c);c=getchar())x=x*10+c-48; x*=b; } inline void add(int x,int y,int co){ fall[++tot]=y; net[tot]=head[x]; head[x]=tot; cost[tot]=co; } void write(int x){ if (x<10) {putchar('0'+x); return;} write(x/10),putchar('0'+x%10); } inline void writeln(int x){ if (x<0) putchar('-'),x*=-1;write(x); putchar('\n'); } void dfs1(int x,int fa){//第一遍dfs f[x]=fa; dep[x]=dep[fa]+1; siz[x]=1; eho(x) if (fall[i]^fa){ co[fall[i]]=cost[i]; id[i>>1]=fall[i];//边所对的点 dfs1(fall[i],x); siz[x]+=siz[fall[i]]; if (siz[son[x]]<siz[fall[i]]) son[x]=fall[i]; } } void dfs2(int x,int top) { be[x]=++tim;df[tim]=x; tp[x]=top; if (son[x]) dfs2(son[x],top); eho(x) if (fall[i]^f[x]&&fall[i]^son[x]) dfs2(fall[i],fall[i]); } void build(int No,int l,int r){ if (l>=r) { ma[No]=co[df[l]]; return; } build(No<<1,l,Mid); build(No<<1|1,Mid+1,r); ma[No]=max(ma[No<<1],ma[No<<1|1]); } void change(int No,int l,int r,int t,int k){ if (l==r) {ma[No]=k; return;} if (t<=Mid) change(No<<1,l,Mid,t,k); else change(No<<1|1,Mid+1,r,t,k); ma[No]=max(ma[No<<1],ma[No<<1|1]); } int query(int No,int l,int r,int L,int R){ if (L>R) {printf("rr"); return 0;} if (L<=l&&r<=R) return ma[No]; if (R<=Mid) return query(No<<1,l,Mid,L,R); if (L >Mid) return query(No<<1|1,Mid+1,r,L,R); return max(query(No<<1,l,Mid,L,Mid),query(No<<1|1,Mid+1,r,Mid+1,R)); } int ask(int x,int y){//查询路径 ans=0; while (tp[x]^tp[y]) { if (dep[tp[x]]<dep[tp[y]]) swap(x,y); ans=max(ans,query(1,1,n,be[tp[x]],be[x])); x=f[tp[x]]; } if (x^y) {//lca 不统计入答案 if (dep[x]<dep[y]) swap(x,y); ans=max(ans,query(1,1,n,be[son[y]],be[x])); } return ans; } int main () { read(n); add(0,0,0);//我们加一条不存在的边,其记号(tot)为1,那么我们的一条边在原读入中就是其tot>>1,因为我们加了2条边。 for (int i=1;i<n;i++) { read(x),read(y),read(w); add(x,y,w); add(y,x,w); } dfs1(1,0); dfs2(1,1); build(1,1,n); while (scanf("%s",ch),ch[0]!='D') { scanf("%d %d",&x,&y); if (ch[0]=='C') change(1,1,n,be[id[x]],y); else writeln(ask(x,y)); } return 0; }