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 ",ans) ;
            }
        }
    }

    return 0 ;
}                                

原文地址:https://www.cnblogs.com/20120125llcai/p/3661929.html