树链剖分 模版

树链剖分 模版

#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

using namespace std;

const int maxn=1000100;
const int INF=(1<<29);

int n;
char op[20];
int u,v,w;
vector<int> G[maxn];
int dep[maxn],son[maxn],fa[maxn],siz[maxn];
int top[maxn];
int id[maxn];
int num;
int val[maxn];
struct Tree
{
    int u,v,val;
};
Tree e[maxn];
struct SegTree
{
    int val;
};
SegTree T[maxn<<2];

void dfs1(int u,int f,int d)
{
    fa[u]=f;
    dep[u]=d;
    son[u]=0;
    siz[u]=1;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==f) continue;
        dfs1(v,u,d+1);
        if(siz[v]>siz[son[u]]) son[u]=v;
        siz[u]+=siz[v];
    }
}

void dfs2(int u,int tp)
{
    top[u]=tp;
    id[u]=++num;
    if(son[u]) dfs2(son[u],tp);
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==fa[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}

void push_up(int rt)
{
    T[rt].val=max(T[rt<<1].val,T[rt<<1|1].val);
}

void build(int l,int r,int rt)
{
    if(l==r){
        T[rt].val=val[l];
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    push_up(rt);
}

void update(int p,int c,int l,int r,int rt)
{
    if(l==r){
        T[rt].val=c;
        return;
    }
    int m=(l+r)>>1;
    if(p<=m) update(p,c,lson);
    else update(p,c,rson);
    push_up(rt);
}

int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) return T[rt].val;
    int m=(l+r)>>1;
    int res=-INF;
    if(L<=m) res=max(res,query(L,R,lson));
    if(R>m) res=max(res,query(L,R,rson));
    return res;
}

int cha(int u,int v)
{
    int res=-INF;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        res=max(res,query(id[top[u]],id[u],1,num,1));
        u=fa[top[u]];
    }
    if(u!=v){
        if(dep[u]>dep[v]) swap(u,v);
        res=max(res,query(id[son[u]],id[v],1,num,1));
    }
    return res;
}

int main()
{
    //freopen("in.txt","r",stdin);
    int casen;
    cin>>casen;
    while(casen--){
        cin>>n;
        for(int i=1;i<=n;i++) G[i].clear();
        for(int i=1;i<n;i++){
            scanf("%d%d%d",&u,&v,&w);
            e[i]={u,v,w};
            G[u].push_back(v);
            G[v].push_back(u);
        }
        num=0;
        dfs1(1,0,1);
        dfs2(1,1);
        for(int i=1;i<n;i++){
            if(dep[e[i].u]>dep[e[i].v]) swap(e[i].u,e[i].v);
            val[id[e[i].v]]=e[i].val;
        }
        build(1,num,1);
        while(~scanf("%s",op)){
            if(op[0]=='D') break;
            if(op[0]=='C'){
                scanf("%d%d",&u,&w);
                int p=id[e[u].v];
                update(p,w,1,num,1);
            }
            else{
                scanf("%d%d",&u,&v);
                printf("%d
",cha(u,v));
            }
        }
    }
    return 0;
}
View Code

SPOJ375,这里是将边权压成点权,凑合着看吧。。。反正手写也不难。。。抄也只是抄两个dfs省时间而已。

没有AC不了的题,只有不努力的ACMER!
原文地址:https://www.cnblogs.com/--560/p/4777361.html