思路:树链剖分的一种,将边权赋值给这条边的儿子节点,(u,v)也就是v节点,u->v,然后线段树维护节点之间的关系。
注意的是,如果u,v在同一天链中的话且dep[u] < dep[v],应该query的是[Seg[u] + 1,Seg[v]]的值,如果不是的话就是这个点到链顶的最大了。
// #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; // #define DEBUG #ifdef DEBUG #define debug(...) printf( __VA_ARGS__ ) #else #define debug(...) #endif #define CLR(x) memset(x, 0,sizeof x) #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back template<class T> inline T Get_Max(const T&a,const T&b){return a < b?b:a;} template<class T> inline T Get_Min(const T&a,const T&b){return a < b?a:b;} typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; const double eps = 1e-10; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int maxn = 10010; int head[maxn], pnt[maxn<<2], cost[maxn<<2], nxt[maxn<<2], ecnt; int fa[maxn], size[maxn], A[maxn], top[maxn], SegId[maxn], TreeId[maxn], son[maxn], dep[maxn]; int Times; void AddEdge(int u,int v,int c){ cost[ecnt] = c;pnt[ecnt] = v;nxt[ecnt] = head[u];head[u] = ecnt++; cost[ecnt] = c;pnt[ecnt] = u;nxt[ecnt] = head[v];head[v] = ecnt++; } int DFS1(int u,int pre,int deep){ dep[u] = deep;fa[u] = pre;size[u] = 1; int tmp = 0; for (int i = head[u];i != -1;i = nxt[i]){ int v = pnt[i]; if (v==pre) continue; A[v] = cost[i]; int ans = DFS1(v, u,deep + 1); size[u] += ans; if (son[u] == -1 || ans > tmp){ tmp = ans; son[u] = v; } } return size[u]; } void DFS2(int u,int header){ top[u] = header; if (son[u] != -1){ SegId[u] = ++Times; TreeId[Times] = u; DFS2(son[u], header); }else if (son[u] == -1){ SegId[u] = ++Times; TreeId[Times] = u; return ; } for (int i = head[u];i != -1;i = nxt[i]){ int v = pnt[i]; if (v!=fa[u]&&v!=son[u]) DFS2(v,v); } } int Max[maxn << 2]; void up(int rt){ Max[rt] = max(Max[rt<<1],Max[rt<<1|1]); } void Build(int rt,int L,int R){ Max[rt] = -inf; if (L == R){ Max[rt] = A[TreeId[L]]; return ; } int mid = (L + R)/2; Build(rt<<1,L,mid); Build(rt<<1|1,mid+1,R); up(rt); } int QueryMax(int l,int r,int rt,int L,int R){ if (l <= L && R <= r){ return Max[rt]; } int mid = (L+R)/2; int ans=-inf; if (l<=mid) ans = max(ans,QueryMax(l,r,rt<<1,L,mid)); if (r>mid) ans = max(ans,QueryMax(l,r,rt<<1|1,mid+1,R)); return ans; } int FindMax(int u,int v){ int f1 = top[u],f2 = top[v]; int ans = -inf; while(f1 != f2){ if (dep[f1] < dep[f2]){ swap(f1,f2); swap(u,v); } ans = max(ans,QueryMax(SegId[f1],SegId[u],1,1,Times)); u = fa[f1]; f1=top[u]; } if (dep[u] < dep[v]){ swap(u,v); } if (u != v) ans = max(ans,QueryMax(SegId[v]+1,SegId[u],1,1,Times)); return ans; } void updata(int pos,int val,int rt,int L,int R){ if (L==R && R==pos){ Max[rt]=val; return ; } int mid=(L+R)/2; if(pos<=mid) updata(pos,val,rt<<1,L,mid); else updata(pos,val,rt<<1|1,mid+1,R); up(rt); } void Change(int pos,int val){ int u = pnt[pos], v = pnt[pos^1]; if(fa[u]==v)swap(u,v); updata(SegId[v],val,1,1,Times); } int wocao[maxn<<2]; int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int t,n; scanf("%d",&t); while(t--){ scanf("%d",&n); Times = ecnt = 0; memset(head, -1,sizeof head); for (int i = 1;i < n;++i){ int u,v,c; scanf("%d%d%d",&u,&v,&c); AddEdge(u,v,c); wocao[i] = head[u]; } memset(son, -1,sizeof son); DFS1(1, -1, 1); A[1] = -inf; DFS2(1, 1); Build(1,1,Times); char op[10]; int x,y; while(true){ scanf("%s",op); if (op[0] == 'D') break; scanf("%d%d",&x,&y); if (op[0] == 'Q') printf("%d\n",FindMax(x,y)); else Change(wocao[x],y); } } return 0; }