2009年广东省大学生程序设计竞赛 H
// 一看这题就会想到应该是用线段树处理
// 一条边的分出来的两个部分点编号并不是连续的,这样很难用线段树处理
// 所以我们就想到给点重新编号,dfs一次,按访问到的点顺序给点编号
// dfs一条边的子树得到的编号肯定是连续,然后我们记录着这个居间
// 这样就可以套线段树了,~~
// by _hehele
#include<cstdio>
#include<iostream>
#include<map>
#include <set>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std ;
#define LL long long
#define mod 1000000007
#define maxn 100010
struct node
{
int to ,next , id ;
}qe[maxn*2];
int map1[maxn] ,top , head[maxn] ;
int _min[maxn] , _max[maxn] ,val[maxn] ;
int ql , qr , vv ;
int Max,Min ;
int mmin[maxn*3] ,mmax[maxn*3] ;
void Unit( int u , int v , int id )
{
qe[top].to = v ;qe[top].next = head[u] ;
qe[top].id = id ;head[u] = top++ ;
}
void dfs( int u ,int fa ,int & kk )
{
int i , v ,id ;
kk++ ;
map1[u] = kk ;
for( i = head[u] ; i != -1 ; i = qe[i].next)
{
v = qe[i].to ;
if(v==fa)continue ;
dfs(v,u,kk) ;
id = qe[i].id ;
_min[id] = map1[v] ;
_max[id] = kk ;
}
}
void update( int L ,int R , int o)
{
if(L == R )
{
mmin[o] = mmax[o] = vv ;
return ;
}
int mid = (L+R)>>1 ;
if( ql <= mid) update(L,mid,o<<1) ;
else update(mid+1,R,o<<1|1) ;
mmin[o] = min(mmin[o<<1|1],mmin[o<<1]) ;
mmax[o] = max(mmax[o<<1|1],mmax[o<<1]) ;
}
void find( int L , int R ,int o )
{
if( ql <= L && qr >= R )
{
Min = min(Min,mmin[o]) ;
Max = max(Max,mmax[o]) ;
return ;
}
int mid = (L+R)>>1 ;
if( ql <= mid ) find(L,mid,o<<1) ;
if(qr > mid ) find(mid+1,R,o<<1|1) ;
}
int main()
{
int i , k ,j ,n , m ;
int T ,case1 = 0 , u , v ;
LL ans ;
char aa[20] ;
//freopen("in.txt","r",stdin) ;
cin >> T ;
while(T--)
{
scanf("%d%d",&n,&m) ;
j = 0;
memset(head,-1,sizeof(head)) ;
top = 0 ;
for( i = 1 ; i <= n ;i++ )
scanf("%d",&val[i]) ;
for( i = 1 ; i < n ;i++ )
{
scanf("%d%d",&u,&v) ;
Unit(u,v,i) ;
Unit(v,u,i) ;
}
dfs(1,-1,j) ;
for( i = 1 ; i <= n ;i++ )
{
ql = map1[i] ;
vv = val[i] ;
update(1,n,1) ;
}
while(m--)
{
scanf("%s",aa) ;
if(aa[0] == 'C')
{
scanf("%d%d",&ql,&vv) ;
ql = map1[ql] ;
update(1,n,1) ;
}
else
{
scanf("%d",&u) ;
ql = _min[u] ;
qr = _max[u] ;
Min = mod ;
Max = -1 ;
find(1,n,1) ;
ans = (LL)Min*Max ;
Min = mod ;
Max = -1 ;
i = ql ; j = qr ;
if( i > 1)
{
ql = 1 ; qr = i-1 ;
find(1,n,1) ;
}
if( j < n )
{
ql = j+1 ;
qr = n ;
find(1,n,1) ;
}
ans += (LL)Min*Max ;
printf("%lld\n",ans) ;
}
}
}
return 0 ;
}