边权树剖板子

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define P pair<int,int>
#define INF 1e18
using namespace std;
const int maxn = 100005;
int head[maxn],Next[maxn<<1],To[maxn<<1],fa[maxn],id[maxn],top[maxn],tp,pos[maxn];
int tot,cnt,size[maxn],son[maxn],deep[maxn],n;
ll tree[maxn<<2];
struct node{
    int u,v,w;
}p[100005];
void add(int u,int v){
    Next[++cnt]=head[u];
    head[u]=cnt;
    To[cnt]=v;
}
void dfs1(int u,int f,int dep){
    fa[u]=f;
    deep[u]=dep+1;
    int mx=0;
    for(int i=head[u]; i!=-1; i=Next[i]){
        int v=To[i];
        if(v==f) continue;
        dfs1(v,u,dep+1);
        size[u]+=size[v];
        if(size[v]>mx) mx=size[v],son[u]=v;
    }
    size[u]++;
}
void dfs2(int u,int tp){
    id[u]=++tot;
    pos[tot]=u;
    top[u]=tp;
    if(son[u]) dfs2(son[u],tp);
    for(int i=head[u]; i!=-1; i=Next[i]){
        int v=To[i];
        if(v!=son[u]&&v!=fa[u])
            dfs2(v,v);
    }
}
void push_up(int rt){
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void updata(int l,int r,int rt,int L,int val){
    if(l==r){
        tree[rt]=val;
        return ;
    }
    int m=(l+r)>>1;
    if(L<=m) updata(lson,L,val);
    else updata(rson,L,val);
    push_up(rt);
}
ll query(int l,int r,int rt,int L,int R){
    if(L<=l&&r<=R){
        return tree[rt];
    }
    int m=(l+r)>>1;
    ll sum=0;
        if(L<=m) sum+=query(lson,L,R);
        if(R>m) sum+=query(rson,L,R);
        return sum;
}
ll Query(int u,int v){
    ll sum=0;
    while(top[u]!=top[v]){
        if(deep[top[u]]<deep[top[v]]) swap(u,v);
         sum+=query(1,n,1,id[top[u]],id[u]);
        u=fa[top[u]];
    }
    if(deep[u]>deep[v]) swap(u,v);
     if(u==v) return sum;
     return sum+query(1,n,1,id[u],id[v]);
}
void init(){
    memset(head,-1,sizeof(head));
    memset(tree,0,sizeof(tree));
    memset(size,0,sizeof(size));
    memset(son,0,sizeof(son));
    cnt=0;
    tot=0;
}
int main(){
    int q,s;
    while(~scanf("%d %d %d",&n,&q,&s)){
    init();
    for(int i=1; i<n; i++){
        scanf("%d %d %d",&p[i].u,&p[i].v,&p[i].w);
        add(p[i].u,p[i].v);
        add(p[i].v,p[i].u);
    }
    dfs1(1,0,0);
    dfs2(1,1);
    for(int i=1;i<n;i++){
        if(deep[p[i].u]>deep[p[i].v]) swap(p[i].u,p[i].v);
        updata(1,n,1,id[p[i].v],p[i].w);
    }
    while(q--){
        int op;
       scanf("%d",&op);
        if(op==0){
            int w;
            scanf("%d",&w);
            printf("%lld
",Query(s,w));
            s=w;
        }else {
            int pos,val;
            scanf("%d %d",&pos,&val);
            updata(1,n,1,id[p[pos].v],val);
        }
    }
}
    return 0;
}
View Code

边权树剖

原文地址:https://www.cnblogs.com/MengX/p/10778621.html