/*

2460 树的统计

 

2008年省队选拔赛浙江

 时间限制: 2 s
 空间限制: 128000 KB
 题目等级 : 大师 Master
 
 
 
题目描述 Description

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。

我们将以下面的形式来要求你对这棵树完成一些操作:

  1. I.                    CHANGE u t : 把结点u的权值改为t
  2. II.                 QMAX u v: 询问从点u到点v的路径上的节点的最大权值
  3. III.               QSUM u v: 询问从点u到点v的路径上的节点的权值和

 

注意:从点u到点v的路径上的节点包括u和v本身

输入描述 Input Description

输入文件的第一行为一个整数n,表示节点的个数。

       接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。

       接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。

       接下来1行,为一个整数q,表示操作的总数。

接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。

 

输出描述 Output Description

       对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。*/


#include<cstdio> #include<iostream> #include<cmath> using namespace std; int head[30008],next[60008],v[60008],n,w[30008],shu[30008],size[30008],fa[30008]; int deep[30008],len,head1[30008],next1[60008],v1[60008],cnt,maxx[30008],sum[30008]; void dfs(int a1) { for(int i=head[a1];i;i=next[i]) if(v[i]!=fa[a1]) { fa[v[i]]=a1; deep[v[i]]=deep[a1]+1; if(size[shu[a1]]<len) { size[shu[a1]]++; shu[v[i]]=shu[a1]; cnt++; next1[cnt]=head1[a1]; head1[a1]=cnt; v1[cnt]=v[i]; } dfs(v[i]); } return; } void dfs1(int a1,int a2,int a3) { a2+=w[a1]; sum[a1]=a2; a3=max(a3,w[a1]); maxx[a1]=a3; for(int i=head1[a1];i;i=next1[i]) dfs1(v1[i],a2,a3); return; } void gai(int a1,int a2) { w[a1]=a2; if(shu[a1]==a1) dfs1(a1,0,-1000000); else dfs1(a1,sum[fa[a1]],maxx[fa[a1]]); return; } pair<int,int> he(int a1,int a2) { int s=0,ma=-1000000; for(;a1!=a2;) { if(deep[a1]<deep[a2]) swap(a1,a2); if(shu[a1]==shu[a2]) { s+=w[a1]; ma=max(w[a1],ma); a1=fa[a1]; } else { if(deep[shu[a1]]<deep[shu[a2]]) swap(a1,a2); s+=sum[a1]; ma=max(maxx[a1],ma); a1=fa[shu[a1]]; } } s+=w[a1]; ma=max(w[a1],ma); return pair<int,int>(s,ma); } int main() { scanf("%d",&n); len=sqrt(n); for(int i=1;i<n;i++) { int a1,a2; scanf("%d%d",&a1,&a2); next[i]=head[a1]; head[a1]=i; v[i]=a2; next[i+n]=head[a2]; head[a2]=i+n; v[i+n]=a1; } for(int i=1;i<=n;i++) { scanf("%d",&w[i]); shu[i]=i; size[i]=1; } dfs(1); for(int i=1;i<=n;i++) if(shu[i]==i) dfs1(i,0,-100000); int m; scanf("%d",&m); for(int i=0;i<m;i++) { char ch[10]; int a1,a2; scanf("%s%d%d",ch,&a1,&a2); if(ch[0]=='C') gai(a1,a2); else { pair<int,int>anss=he(a1,a2); if(ch[1]=='S') printf("%d\n",anss.first); else printf("%d\n",anss.second); } } return 0; }
posted on 2016-01-21 17:25  xiyuedong  阅读(139)  评论(0编辑  收藏  举报