Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输入的第一行为一个整数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之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
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
Sample Output
4
1
2
2
10
6
5
6
5
16
HINT
Source
代码:
#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<vector>
#include<math.h>
#include<map>
#include<queue>
#include<algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
typedef pair<int,int> pii;
const int maxn = 5e5+10;
int n,q,w[maxn];
struct Edge{//边集
int to,nex;
}edge[maxn*2];
int tot,head[maxn],mark;
void init(){
tot=mark=0;
memset (head,-1,sizeof (head));
}
void addedge(int u,int v){
edge[tot].to=v;
edge[tot].nex=head[u];
head[u]=tot++;
}
int fa[maxn],sz[maxn],son[maxn],dep[maxn];
void dfs1(int u,int pre,int depth){//求重儿子、深度、父节点、子树大小
fa[u]=pre;dep[u]=depth;
sz[u]=1;son[u]=-1;
for (int i=head[u];i!=-1;i=edge[i].nex){
int v=edge[i].to;
if (v==pre)continue;
dfs1(v,u,depth+1);
sz[u]+=sz[v];
if (son[u]==-1||sz[son[u]]<sz[v])son[u]=v;
}
}
int id[maxn],top[maxn],pree[maxn];
void dfs(int u,int tp){//求链
top[u]=tp;
id[u]=++mark;
pree[mark]=u;
if (son[u]==-1)return;
dfs(son[u],tp);
for (int i=head[u];i!=-1;i=edge[i].nex){
int v=edge[i].to;
if (v==fa[u]||v==son[u])continue;
dfs(v,v);
}
}
int sum[maxn*4],Max[maxn*4];
void push_up(int rt){
sum[rt]=sum[rt*2]+sum[rt*2+1];
Max[rt]=max(Max[rt*2],Max[rt*2+1]);
}
void build(int rt,int l,int r){
if (l==r){
sum[rt]=Max[rt]=w[pree[l]];
return;
}
int mid=(l+r)/2;
build(rt*2,l,mid);
build(rt*2+1,mid+1,r);
push_up(rt);
}
void update(int rt,int l,int r,int pos,int val){//修改pos位置在值
if (l==r){
sum[rt]=Max[rt]=val;
return;
}
int mid=(l+r)/2;
if (pos<=mid)update(rt*2,l,mid,pos,val);
else update(rt*2+1,mid+1,r,pos,val);
push_up(rt);
}
int query(int rt,int l,int r,int L,int R){//得到L,R的最大值
if (l>=L&&r<=R){
return Max[rt];
}
int mid=(l+r)/2;
int ans=-inf;
if (L<=mid) ans=max(ans,query(rt*2,l,mid,L,R));
if (R>mid) ans=max(ans,query(rt*2+1,mid+1,r,L,R));
return ans;
}
int querysum(int rt,int l,int r,int L,int R){//得到L,R的sum值
if (l>=L&&r<=R){
return sum[rt];
}
int ans=0;
int mid = (l+r)/2;
if (L<=mid)ans+=querysum(rt*2,l,mid,L,R);
if (R>mid)ans+=querysum(rt*2+1,mid+1,r,L,R);
return ans;
}
int getMax(int x,int y){
int fx=top[x],fy=top[y];
int M=-inf;
while (fx!=fy){
if (dep[fx]<dep[fy]){
swap(x,y);swap(fx,fy);
}
M=max(M,query(1,1,n,id[fx],id[x]));
x=fa[fx];
fx=top[x];
}
if (dep[x]>dep[y])swap(x,y);
M=max(M,query(1,1,n,id[x],id[y]));
return M;
}
int getSum(int x,int y){
int fx=top[x],fy=top[y];
int ans=0;
while (fx!=fy){
if (dep[fx]<dep[fy]){
swap(x,y);swap(fx,fy);
}
ans+=querysum(1,1,n,id[fx],id[x]);
x=fa[fx];
fx=top[x];
}
if (dep[x]>dep[y])swap(x,y);
ans+=querysum(1,1,n,id[x],id[y]);
return ans;
}
char s[10];
void fuck(){
for (int i=1;i<=n;i++){
printf ("%d ",query(1,1,n,i,i));
}
printf ("\n");
}
int main ()
{
scanf ("%d",&n);
memset (sum,0,sizeof (sum));
memset (Max,0,sizeof (Max));
init();
int u,v;
for (int i=1;i<=n-1;i++){
scanf ("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs1(1,-1,1);
dfs(1,1);
int tmp;
for (int i=1;i<=n;i++){
scanf("%d",&w[i]);
}
build(1,1,n);
int t;
scanf ("%d",&q);
while(q--){
scanf ("%s",s);
if (s[0]=='C'){
scanf ("%d%d",&u,&t);
w[u]=t;
update(1,1,n,id[u],t);
}else {
scanf ("%d%d",&u,&v);
if (s[1]=='M'){
printf ("%d\n",getMax(u,v));
}else {
printf ("%d\n",getSum(u,v));
}
}
}
return 0;
}
/*
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
8
1 5
6 2
3 6
1 4
7 8
5 8
1 2
1 2 3 4 5 6 7 8
10
QSUM 1 5
QMAX 1 5
CHANGE 1 100
QMAX 7 8
QSUM 5 4
CHANGE 4 1
QSUM 4 8
QMAX 5 8
CHANGE 3 -50
QSUM 3 8
*/