一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
#include<iostream> #include<cstdio> #include<vector> #include<cstring> using namespace std; const int maxn = 3E4 + 30; int n,m,cur = 0,i,j,cnt = 0,qx,qy,qz,am,as,Now,ret; int L[maxn],anc[maxn][20],c_sum[maxn*20],c_max[maxn*20],va[maxn],belong[maxn],head[maxn],Size[maxn],next[maxn]; int father[maxn],c_size[maxn],Lt[maxn*20],Rt[maxn*20]; bool vis[maxn],heavy[maxn]; vector <int> v[maxn]; vector <int> c[maxn]; void dfs(int k) { int Max = 0,t = 0;; for (int l = 0; l < v[k].size(); l++) { int to = v[k][l]; if (vis[to]) continue; vis[to] = 1; father[to] = k; L[to] = L[k] + 1; dfs(to); Size[k] += Size[to]; if (Size[to] > Max) Max = Size[to],t = to; } if (t) heavy[t] = 1,next[k] = t; } void build_tree(int o,int l,int r) { if (l == r) { c_max[o] = c_sum[o] = va[c[cnt][l]]; return; } int mid = (l + r) >> 1; ++cur; Lt[o] = cur; build_tree(cur,l,mid); ++cur; Rt[o] = cur; build_tree(cur,mid + 1,r); c_max[o] = max(c_max[Lt[o]],c_max[Rt[o]]); c_sum[o] = c_sum[Lt[o]] + c_sum[Rt[o]]; } void search(int k) { ++cnt; c_size[cnt] = 0; c[cnt].push_back(0); while (k) { belong[k] = cnt; c[cnt].push_back(k); k = next[k]; ++c_size[cnt]; } head[cnt] = ++cur; build_tree(cur,1,c_size[cnt]); } int get_order() { char c_m[10]; scanf("%s",&c_m); if (c_m[0] == 'C') return 1; if (c_m[1] == 'M') return 2; return 3; } void Modify(int o,int l,int r) { if (l == r) { c_sum[o] = c_max[o] = qy; va[c[qz][l]] = qy; return; } int mid = (l + r) >> 1; int Mid = c[qz][mid]; if (L[Mid] >= L[qx]) Modify(Lt[o],l,mid); else Modify(Rt[o],mid + 1,r); c_sum[o] = c_sum[Lt[o]] + c_sum[Rt[o]]; c_max[o] = max(c_max[Lt[o]],c_max[Rt[o]]); } int fa(int u,int v) { int log; for (log = 0; L[u] - (1<<log) > 0; log++); ++log; for (j = log; j >= 0; j--) if (L[u] - (1<<j) >= L[v]) u = anc[u][j]; if (u == v) return u; for (j = log; j >= 0; j--) if (anc[u][j] != anc[v][j]) { u = anc[u][j]; v = anc[v][j]; } return anc[u][0]; } int solve(int o,int l,int r,int pos) { int ret; if (L[c[Now][l]] > L[qz] && L[c[Now][r]] <= L[pos]) { as += c_sum[o]; am = max(am,c_max[o]); return c[Now][l]; } int mid = (l + r) >> 1; int Mid = c[Now][mid]; if (L[Mid] > L[qz]) { if (L[pos] > L[Mid])solve(Rt[o],mid + 1,r,pos); return solve(Lt[o],l,mid,pos); } else return solve(Rt[o],mid + 1,r,pos); } void Up(int k) { for (;;) { if (!heavy[k] || heavy[k] && k == qz) as += va[k]; am = max(am,va[k]); if (k == qz) return; if (!heavy[k]) { k = father[k]; continue; } Now = belong[k]; int ret = solve(head[Now],1,c_size[Now],k); k = ret; k = father[k]; } } void Q() { as = 0; am = -2E9; Up(qx); Up(qy); as -= va[qz]; } void dfs2(int k) { anc[k][0] = father[k]; for (int log = 1; L[k] - (1<<log) > 0; log++) anc[k][log] = anc[anc[k][log-1]][log-1]; for (int l = 0; l < v[k].size(); l++) { int to = v[k][l]; if (vis[to]) continue; vis[to] = 1; dfs2(to); } } int main() { #ifdef YZY freopen("yzy.txt","r",stdin); #endif memset(anc,-1,sizeof(anc)); cin >> n; for (i = 1; i < n; i++) { int x,y; scanf("%d%d",&x,&y); v[x].push_back(y); v[y].push_back(x); } for (i = 1; i <= n; i++) { scanf("%d",&va[i]); father[i] = i; anc[i][0] = i; Size[i] = 1; } memset(heavy,0,sizeof(heavy)); memset(vis,0,sizeof(vis)); L[1] = 1; vis[1] = 1; dfs(1); memset(vis,0,sizeof(vis)); vis[1] = 1; dfs2(1); anc[1][0] = -1; for (i = 1; i <= n; i++) if (heavy[i] && !heavy[father[i]]) search(i); cin >> m; while (m--) { int opt = get_order(); if (opt == 1) { scanf("%d%d",&qx,&qy); qz = belong[qx]; if (qz) Modify(head[qz],1,c_size[qz]); else va[qx] = qy; } if (opt == 2) { scanf("%d%d",&qx,&qy); if (L[qx] < L[qy]) swap(qx,qy); if (qx == qy) qz = qx; else qz = fa(qx,qy); Q(); printf("%d\n",am); } if (opt == 3) { scanf("%d%d",&qx,&qy); if (L[qx] < L[qy]) swap(qx,qy); if (qx == qy) qz = qx; else qz = fa(qx,qy); Q(); printf("%d\n",as); } } return 0; }