树链剖分模板


样题链接

http://www.spoj.com/problems/QTREE/


模板如下:

#include <bits/stdc++.h>
using namespace std ;

typedef long long ll ;
const int maxn = 1e4 + 5 ;

int deep[maxn] ;
int size[maxn] ;
int father[maxn] ;
int son[maxn] ;
int id[maxn] ;
int value[maxn] ;
int top[maxn] ;

int num ;
vector<int> point[maxn] ;
struct edge{
    int st , ed , val ;
};
edge save[maxn] ;

void dfs_first(int u , int fa , int dp){
    deep[u] = dp ;
    size[u] = 1 ;
    son[u] = 0 ;
    father[u] = fa ;
    for(int i = 0 ; i < point[u].size() ; i ++ ){
        int ed = point[u][i] ;
        if(fa == ed) continue ;
        dfs_first(ed , u , dp + 1) ;
        size[u] += size[ed] ;
        if(size[ son[u] ] < size[ed])
            son[u] = ed ;
    }
}
void dfs_second(int u , int temp){
    top[u] = temp ;
    id[u] = ++ num ;
    if(son[u]) dfs_second(son[u] , temp) ;
    for(int i = 0 ; i < point[u].size() ; i ++ ){
        int ed = point[u][i] ;
        if(ed == father[u] || ed == son[u]) continue ;
        dfs_second(ed , ed) ;
    }
}
void init(int n ){
    for(int i = 1 ; i <= n ; i ++ ) point[i].clear() ;
    num = 0 ;
}

/// make tree
struct Tree{
    int l , r , val ;
};
Tree tree[maxn * 4] ;
void push_up(int node){
    tree[node].val = max(tree[node<<1].val , tree[node<<1|1].val) ;
}
void build(int l , int r , int node) {
    tree[node].l = l ;
    tree[node].r = r ;
    if(l == r){
        tree[node].val = value[l] ;
        return ;
    }
    int mid = (l + r) >> 1 ;
    build(l , mid , node << 1) ;
    build(mid + 1 , r , node << 1 | 1) ;
    push_up(node) ;
}
void update(int node , int pos , int val){
    if(tree[node].l == tree[node].r){
        tree[node].val = val ;
        return ;
    }
    int mid = (tree[node].l + tree[node].r) >> 1 ;
    if(pos <= mid)
        update(node << 1 , pos , val) ;
    else
        update(node << 1 | 1 , pos , val) ;
    push_up(node) ;
}

int query(int node , int l , int r){
    if(tree[node].l > r || tree[node].r < l) return 0 ;
    if(tree[node].l >= l && tree[node].r <= r)  return tree[node].val ;
    int ans = 0 ;
    int mid = (tree[node].l + tree[node].r) >> 1 ;
    if(l <= mid)
        ans = max(ans , query(node << 1 , l , r)) ;
    if(r > mid)
        ans = max(ans , query(node << 1 | 1 , l , r )) ;
    return ans ;
}

int work(int u , int v){
    int top_u = top[u] , top_v = top[v] ;
    int ans = 0 ;
    while(top_u != top_v){
        if(deep[top_u] < deep[top_v]){
            swap(top_u , top_v) ;
            swap(u , v) ;
        }
        ans = max(query(1 , id[top_u] , id[u]) , ans) ;
        u = father[top_u] ;
        top_u = top[u] ;
    }
    if(u == v) return ans ;
    if(deep[u] > deep[v]) swap(u , v) ;

    ans = max(ans , query(1 , id[son[u]] , id[v])) ;
    return ans ;
}
/*
1
3
1 2 2
2 3 1
*/

int main(){
    int kase ; scanf("%d" , &kase) ;
    int a , b , w ;
    while( kase -- ){
        int n ; scanf("%d" , &n) ;
        init(n) ;
        for(int i = 1 ; i < n ; i ++ ){
            scanf("%d %d %d" , &save[i].st , &save[i].ed , &save[i].val) ;
            a = save[i].st , b = save[i].ed ;
            point[a].push_back(b) ;
            point[b].push_back(a) ;
        }
        dfs_first(1 , 0 , 1) ;
        dfs_second(1 , 1) ;

        for(int i = 1 ; i < n ; i ++ ){
            a = save[i].st , b = save[i].ed , w = save[i].val ;
            if(deep[a] < deep[b]) swap(save[i].st , save[i].ed) ;
            value[ id[ save[i].st ] ] = w ;
        }
        build(1 , num , 1) ;

        char read[20] ;
        while(~ scanf("%s" , read)){
            if(read[0] == 'D') break ;
            scanf("%d %d" , &a , &b) ;
            if(read[0] == 'Q')
                printf("%d\n" , work(a , b)) ;
            else
                update(1 , id[save[a].st] , b) ;
        }
    }
    return 0 ;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值