题目描述
一棵树上有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”的形式给出。
输出格式:
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
输入输出样例
输入样例#1:
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
输出样例#1:
4
1
2
2
10
6
5
6
5
16
说明
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
树链剖分模板。。。
code:
//By Menteur_Hxy
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#define ll long long
#define f(a,b,c) for(int a=b;a<=c;a++)
using namespace std;inline ll rd() {ll x=0,fla=1; char c=' ';while(c>'9' || c<'0') {if(c=='-') fla=-fla; c=getchar();}while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();return x*fla;
}inline void out(ll x){int a[25],wei=0;if(x<0) putchar('-'),x=-x;for(;x;x/=10) a[++wei]=x%10;if(wei==0){ puts("0"); return;}for(int j=wei;j>=1;--j) putchar('0'+a[j]);putchar('\n');
}const int MAX=300100;//直接开了十倍qwq
const int INF=0x3f3f3f3f;
int n,cnt,N;int head[MAX],W[MAX],size[MAX],h[MAX],fa[MAX],son[MAX];
//W 点权 size 树的大小 h 深度 fa 父亲 son 重儿子 int num[MAX],top[MAX],tree[MAX],maxn[MAX],sumn[MAX];
//num 在线段树编号 top 链最上面的点 tree 线段树编号对应的点 struct edges{int next,to;
}edge[MAX]; void add(int a,int b) {edge[++cnt]=(edges) {head[a],b}; head[a]=cnt;edge[++cnt]=(edges) {head[b],a}; head[b]=cnt;
}void dfs1(int u,int pre,int dep) {size[u]=1; h[u]=dep; fa[u]=pre;//initint mason=0;for(int i=head[u];i;i=edge[i].next) if(edge[i].to!=pre) {int v=edge[i].to;dfs1(v,u,dep+1);size[u]+=size[v];if(size[v]>mason) {mason=size[v];son[u]=v;}}
}void dfs2(int u,int pre) {if(son[pre]!=u) top[u]=u;else top[u]=top[pre];num[u]=++N;if(son[u]) dfs2(son[u],u);for(int i=head[u];i;i=edge[i].next)if(edge[i].to!=pre && edge[i].to !=son[u])dfs2(edge[i].to,u);
}void build_sum(int cur,int l,int r) {if(l==r) {sumn[cur]=W[tree[l]];return ;}int mid=(l+r)>>1;build_sum(cur<<1,l,mid);build_sum(cur<<1|1,mid+1,r);sumn[cur]=sumn[cur<<1]+sumn[cur<<1|1];//update_sum
}void build_max(int cur,int l,int r) {if(l==r) {maxn[cur]=W[tree[l]];return ;}int mid=(l+r)>>1;build_max(cur<<1,l,mid);build_max(cur<<1|1,mid+1,r);maxn[cur]=max(maxn[cur<<1],maxn[cur<<1|1]);//update_max
}void po_ch_sum(int cur,int l,int r,int x,int v) {//point_change_sumif(l==r) {sumn[cur]=v;return ;}int mid=(l+r)>>1;if(x<=mid) po_ch_sum(cur<<1,l,mid,x,v);else po_ch_sum(cur<<1|1,mid+1,r,x,v);sumn[cur]=sumn[cur<<1]+sumn[cur<<1|1];//update_sum
}void po_ch_max(int cur,int l,int r,int x,int v) {//point_change_maxif(l==r) {maxn[cur]=v;return ;}int mid=(l+r)>>1;if(x<=mid) po_ch_max(cur<<1,l,mid,x,v);else po_ch_max(cur<<1|1,mid+1,r,x,v);maxn[cur]=max(maxn[cur<<1],maxn[cur<<1|1]);
}int query_sum(int cur,int l,int r,int L,int R) {if(L<=l&&r<=R) return sumn[cur];int mid=(l+r)>>1,ans=0;if(L<=mid) ans+=query_sum(cur<<1,l,mid,L,R);if(R>mid) ans+=query_sum(cur<<1|1,mid+1,r,L,R);return ans;
}int query_max(int cur,int l,int r,int L,int R) {if(L<=l&&r<=R) return maxn[cur];int mid=(l+r)>>1,ans=-INF;if(L<=mid) ans=max(ans,query_max(cur<<1,l,mid,L,R));if(R>mid) ans=max(ans,query_max(cur<<1|1,mid+1,r,L,R));return ans;
}void INIT() {dfs1(1,0,1);// size h fa sondfs2(1,0);//top numf(i,1,n) tree[num[i]]=i;//tree//建树: build_sum(1,1,N);build_max(1,1,N);
}void solve() {int q=rd(),a,b,ans=0,f1,f2;char opt[6];f(i,1,q) {scanf("%s",opt);a=rd(),b=rd(),ans=0;if(opt[0]=='C') {//HCANGEpo_ch_sum(1,1,N,num[a],b);po_ch_max(1,1,N,num[a],b);}else {f1=top[a],f2=top[b];if(opt[1]=='M') ans=-INF;while(f1!=f2) {if(h[f1]<h[f2]) {swap(a,b);swap(f1,f2);}if(opt[1]=='S') ans+=query_sum(1,1,N,num[f1],num[a]);else ans=max(ans,query_max(1,1,N,num[f1],num[a]));a=fa[f1];f1=top[a];}if(num[a]>num[b]) swap(a,b);if(opt[1]=='S') ans+=query_sum(1,1,N,num[a],num[b]);else ans=max(ans,query_max(1,1,N,num[a],num[b]));out(ans);}}
}int main() {n=rd();f(i,1,n-1) add(rd(),rd());f(i,1,n) W[i]=rd();INIT();solve();return 0;
}