spoj Qtree1

说几个需要注意的问题:

1.多组样例时初始化问题

首先 lca 的 f 数组和 根的 d 值需要初始化

其次,树剖的son值和num需要初始化

2.把边赋给点时需要注意的问题

首先,根节点对应的边应该注意赋初值

其次,线段树是对编号之后的树进行建树,应该注意。

最后,因为lca的边不应该被算上,所以处理方式和点的不太一样,注意一下。

#include<bits/stdc++.h>
#define lc l,mid,x<<1
#define rc mid+1,r,x<<1|1
using namespace std;
typedef long long LL;
typedef int lint;
const lint maxn = 100005;
const lint maxm = 200005;
const lint inf= 0x3f3f3f3f;
lint tot,ide[maxm],he[maxn],ver[maxm],ne[maxm];
LL cost[maxm];
void add( lint x,lint y,LL c,lint i ){
    ver[++tot] = y;
    ne[tot] = he[x];
    he[x] = tot;
    cost[i]  = c;
    ide[tot] = i;
}
lint sz[maxn],f[maxn],son[maxn],d[maxn],vertice[maxm],edge[maxn];
void dfs1(lint x){
    sz[x] = 1;
    lint mm = 0;son[x] = 0;
    for( lint cure = he[x];cure;cure = ne[cure] ){
        lint y = ver[cure];
        if( y == f[x] ) continue;
        vertice[ ide[cure] ] = y;
        edge[y] = ide[cure];
        d[y] = d[x]+1;
        f[y] = x;
        dfs1(y);
        sz[x] += sz[y];
        if( sz[y] > mm ){
            mm = sz[y];
            son[x] = y;
        }
    }
}
lint top[maxn],h[maxn],id[maxn],num;
void dfs2( lint x ){
    h[x] = ++num;
    id[num] = x;
    if( son[ f[x] ] == x ){
        top[x] = top[ f[x] ];
    }else{
        top[x] = x;
    }
    if( son[x] ){
        dfs2(son[x]);
    }
    for( lint cure = he[x];cure;cure = ne[cure] ){
        lint y = ver[cure];
        if( y == f[x] || y == son[x] )continue;
        dfs2(y);
    }
}
LL tree[4*maxn];
void push_up( lint x ){
    tree[x] = max( tree[x<<1],tree[x<<1|1] );
}
void build_tree( lint l,lint r,lint x ){
    if( l == r ){
        tree[x] = cost[edge[id[l] ]];
        return;
    }
    lint mid = l+r>>1;
    build_tree(lc);
    build_tree(rc);
    push_up(x);
}
void update( lint ll,lint rr,LL v,lint l,lint r,lint x ){
    if( ll <= l && rr >= r ){
        tree[x] = v;
        return;
    }
    lint mid = l+r >> 1;
    if( ll <= mid ) update( ll,rr,v,lc );
    if( rr > mid ) update( ll,rr,v,rc );
    push_up(x);
}
LL ask( lint ll,lint rr,lint l,lint r,lint x ){
    if( ll <= l&& rr >= r ){
        return tree[x];
    }
    LL mm = -inf;
    lint mid = l+r>>1;
    if( ll <= mid ){
        mm = max( mm,ask( ll,rr,lc ) );
    }
    if( rr > mid ){
        mm = max( mm,ask( ll,rr,rc ) );
    }
    return mm;
}
LL solveask( lint x,lint y ){
    LL res = -inf;
    while( top[x] != top[y] ){
        if( d[ top[x] ] < d[ top[y] ] )swap( x,y );
        res = max(res, ask( h[ top[x] ],h[x],1,num,1 ));
        x = f[ top[x] ];
    }
    if( d[x] < d[y] ){
        swap( x,y );
    }
    if( x != y ){
        res =max(res, ask( h[ son[y] ],h[x],1,num,1 ));
    }
    return res;
}
void init( lint n ){
    tot = 1;num = 0;cost[0] = -inf;
    for( lint i = 0;i <= n;i++ ) {
        he[i] = 0;
    }
}
int main(){
    lint T,n;
    scanf("%d",&T);
    while( T-- ) {
        scanf("%d", &n);
        init(n);
        LL c;
        for (lint x, y, i = 1; i <= n - 1; i++) {
            scanf("%d%d%lld", &x, &y, &c);
            add(x, y, c, i);
            add(y, x, c, i);
        }
        dfs1(1);
        dfs2(1);
        build_tree(1, n, 1);
        char op[20];
        while (1) {
            scanf("%s", op);
            if (!strcmp(op, "DONE"))break;
            lint x, y;
            if (!strcmp(op, "QUERY")) {
                scanf("%d%d", &x, &y);
                if (x == y) {
                    printf("0\n");
                    continue;
                }
                LL ans = solveask(x, y);
                printf("%lld\n", ans);
            } else {
                scanf("%d%d", &x, &y);
                update(h[vertice[x]], h[vertice[x]], y, 1, num, 1);
            }
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值