ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P4949 最短距离(基环树+树链剖分)

2019-04-18 09:44:54  阅读:378  来源: 互联网

标签:剖分 fa fx fy LL id 基环树 P4949 size


题目

P4949 最短距离

做法

先把非树边提出来

查询\((x,y)\)的最短距离就分类查询:树上\((x,y)\)距离,经过非树边距离

带边权查询链长,一个烂大街的套路:树链剖分,节点维护树边距离

待修改随便搞搞就行

Code

#include<bits/stdc++.h>
typedef int LL;
const LL maxn=3e5+9;
inline LL Read(){
    LL x(0),f(1); char c=getchar();
    while(c<'0' || c>'9'){
        if(c=='-') f=-1; c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<3)+(x<<1)+c-'0'; c=getchar();
    }
    return x*f;
}
struct node{
    LL to,nxt,d;
}dis[maxn];
LL num;
LL head[maxn];
inline void Add(LL u,LL v,LL w){
    dis[++num]=(node){v,head[u],w}; head[u]=num;
}
struct E{
    LL u,v,w;
}e[maxn];
LL n,m;
LL n_tree,n_u,n_v,tim,n_d;
LL dep[maxn],size[maxn],visit[maxn],fa[maxn],val[maxn],bel[maxn],son[maxn],dx[maxn],id[maxn],top[maxn];
void Dfs1(LL u,LL f){
    dep[u]=dep[f]+1;
    size[u]=1; visit[u]=true;
    for(LL i=head[u];i;i=dis[i].nxt){
        LL v(dis[i].to); if(v==f) continue;
        if(visit[v]){
            n_tree=i+1>>1; n_u=u; n_v=v; n_d=dis[i].d;
            continue;
        }
        Dfs1(v,u); size[u]+=size[v];
        fa[v]=u; val[v]=dis[i].d; bel[i+1>>1]=v;
        if(size[son[u]]<size[v]) son[u]=v;
    }
}
void Dfs2(LL u,LL up){
    dx[++tim]=u; id[u]=tim;
    top[u]=up;
    if(son[u]) Dfs2(son[u],up);
    for(LL i=head[u];i;i=dis[i].nxt){
        LL v(dis[i].to); if(v==fa[u] || v==son[u] || (i+1>>1)==n_tree) continue;
        Dfs2(v,v);
    }
}
struct Bit{
    LL t[maxn];
    inline LL Lowbit(LL x){
        return x&-x;
    }
    inline void Add(LL x,LL val){
        for(;x<=n;x+=Lowbit(x)) t[x]+=val;
    }
    inline LL Qy(LL x){
        LL ret(0);
        for(;x;x-=Lowbit(x)) ret+=t[x];
        return ret;
    }
    inline LL Query(LL l,LL r){
        return Qy(r)-Qy(l-1);
    }
}Bt;
inline LL Query(LL x,LL y){
    LL ret(0);
    LL fx(top[x]),fy(top[y]);
    while(fx!=fy){
        if(dep[fx]>=dep[fy]){
            ret+=Bt.Query(id[fx],id[x]); x=fa[fx];
        }else{
            ret+=Bt.Query(id[fy],id[y]); y=fa[fy];
        }
        fx=top[x]; fy=top[y];
    }
    if(dep[x]<=dep[y])
        ret+=Bt.Query(id[x],id[y])-val[x];
    else
        ret+=Bt.Query(id[y],id[x])-val[y];
    return ret;
}
int main(){
    n=Read(); m=Read();
    for(LL i=1;i<=n;++i){
        LL u(Read()),v(Read()),w(Read());
        Add(u,v,w); Add(v,u,w);
        e[i]=(E){u,v,w};
    }
    Dfs1(1,0); Dfs2(1,1);
    for(LL i=1;i<=n;++i)
        Bt.Add(id[i],val[i]);
    while(m--){
        LL op(Read()),x(Read()),y(Read());
        if(op==1){
            if(x==n_tree){
                n_d=y;
                continue;
            }
            LL v(bel[x]);
            Bt.Add(id[v],-val[v]);
            Bt.Add(id[v],val[v]=y);
        }else{
            printf("%d\n",std::min(Query(x,y),std::min(Query(x,n_u)+Query(y,n_v)+n_d,Query(x,n_v)+Query(y,n_u)+n_d)));
        }
    }
    return 0;
}

标签:剖分,fa,fx,fy,LL,id,基环树,P4949,size
来源: https://www.cnblogs.com/y2823774827y/p/10727654.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有