题目描述
一棵树上有 $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$ 本身。
输入格式
输入文件的第一行为一个整数 nn,表示节点的个数。
接下来 $n−1$ 行,每行 2 个整数 a 和 b,表示节点 a 和节点 b 之间有一条边相连。
接下来一行 n 个整数,第 i个整数 $w_i$ 表示节点 i 的权值。
接下来 1 行,为一个整数 q,表示操作的总数。
接下来 q 行,每行一个操作,以 $CHANGE u v$
或者$ QMAX u v$或者 $QSUM u v$
的形式给出。
输出格式
对于每个 $QMAX$或者 $QSUM$的操作,每行输出一个整数表示要求输出的结果。
输入输出样例
输入
4 1 2 2 3 4 1 4 2 1 3 12 QMAX 3 4 QMAX 3 3 QMAX 3 2 QMAX 2 3 QSUM 3 4 QSUM 2 1 CHANGE 1 5 QMAX 3 4 CHANGE 3 6 QMAX 3 4 QMAX 2 4 QSUM 3 4
输出
4 1 2 2 10 6 5 6 5 16
说明/提示
对于 $100 \%$的数据,保证 $1le n le 3 imes 10^4$,$0le qle 2 imes 10^5$。
中途操作中保证每个节点的权值 w 在 $-3 imes 10^4$ 到$ 3 imes 10^4$之间。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int head[100001],tot,n,q,w[100001],d[1000001],fa[1000001],size[1000001],sum,top[1000001],pos[10000001]; 4 struct data { 5 int to,nxt; 6 } e[1000001]; 7 struct SegmentTree { 8 int sum,l,r,mx; 9 #define l(x) tree[x].l 10 #define r(x) tree[x].r 11 #define sum(x) tree[x].sum 12 #define mx(x) tree[x].mx 13 } tree[4000004]; 14 void add(int x,int y) { 15 e[++tot].to=y; 16 e[tot].nxt=head[x]; 17 head[x]=tot; 18 } 19 void build(int p,int l,int r) { 20 l(p)=l,r(p)=r; 21 if(l==r) 22 return; 23 int mid=l+r>>1; 24 build(p<<1,l,mid); 25 build(p<<1|1,mid+1,r); 26 } 27 void change(int p,int x,int v) { 28 if(l(p)==r(p)) { 29 sum(p)=v; 30 mx(p)=v; 31 return; 32 } 33 int mid=l(p)+r(p)>>1; 34 if(x<=mid) change(p<<1,x,v); 35 else change(p<<1|1,x,v); 36 mx(p)=max(mx(p<<1),mx(p<<1|1)); 37 sum(p)=sum(p<<1)+sum(p<<1|1); 38 } 39 int query_sum(int p,int l,int r) { 40 if(l<=l(p)&&r>=r(p)) 41 return sum(p); 42 int val=0; 43 int mid=l(p)+r(p)>>1; 44 if(l<=mid) val+=query_sum(p<<1,l,r); 45 if(r>mid) val+=query_sum(p<<1|1,l,r); 46 return val; 47 } 48 int query_mx(int p,int l,int r) { 49 if(l<=l(p)&&r>=r(p)) 50 return mx(p); 51 int val=-(1<<30); 52 int mid=l(p)+r(p)>>1; 53 if(l<=mid) val=max(val,query_mx(p<<1,l,r)); 54 if(r>mid) val=max(val,query_mx(p<<1|1,l,r)); 55 return val; 56 } 57 void dfs1(int x) { 58 size[x]=1; 59 for(int i=head[x]; i; i=e[i].nxt) { 60 int v=e[i].to; 61 if(v==fa[x]) continue; 62 fa[v]=x; 63 d[v]=d[x]+1; 64 dfs1(v); 65 size[x]+=size[v]; 66 } 67 } 68 void dfs2(int x,int t) { //jiedian top 69 int node=0; 70 pos[x]=++sum; 71 top[x]=t; 72 for(int i=head[x]; i; i=e[i].nxt) 73 if(d[e[i].to]>d[x]&&size[e[i].to]>size[node]) 74 node=e[i].to; 75 if(node==0) 76 return; 77 dfs2(node,t); 78 for(int i=head[x]; i; i=e[i].nxt) 79 if(d[e[i].to]>d[x]&&node!=e[i].to) 80 dfs2(e[i].to,e[i].to); 81 } 82 int solve_sum(int x,int y) { 83 int val=0; 84 while(top[x]!=top[y]) { 85 if(d[top[x]]<d[top[y]]) swap(x,y); 86 val+=query_sum(1,pos[top[x]],pos[x]); 87 x=fa[top[x]]; 88 } 89 if(pos[x]>pos[y]) swap(x,y); 90 val+=query_sum(1,pos[x],pos[y]); 91 return val; 92 } 93 int solve_mx(int x,int y) { 94 int val=-(1<<30); 95 while(top[x]!=top[y]) { 96 if(d[top[x]]<d[top[y]]) swap(x,y); 97 val=max(val,query_mx(1,pos[top[x]],pos[x])); 98 x=fa[top[x]]; 99 } 100 if(pos[x]>pos[y]) swap(x,y); 101 val=max(val,query_mx(1,pos[x],pos[y])); 102 return val; 103 } 104 void init() { 105 scanf("%d",&n); 106 for(int i=1,x,y; i<n; i++) 107 scanf("%d%d",&x,&y),add(x,y),add(y,x); 108 for(int i=1; i<=n; i++) 109 scanf("%d",&w[i]); 110 } 111 void solve() { 112 build(1,1,n); 113 for(int i=1; i<=n; i++) 114 change(1,pos[i],w[i]); 115 scanf("%d",&q); 116 for(int i=1; i<=q; i++) { 117 char c[10]; 118 int x,y; 119 scanf("%s%d%d",c,&x,&y); 120 if(c[0]=='C') 121 change(1,pos[x],y); 122 else { 123 if(c[1]=='M') 124 printf("%d ",solve_mx(x,y)); 125 else 126 printf("%d ",solve_sum(x,y)); 127 } 128 } 129 } 130 int main() { 131 init(); 132 dfs1(1); 133 dfs2(1,1); 134 solve(); 135 return 0; 136 }