codeforces838B Diverging Directions -- 树链剖分 + 线段树

来源:互联网 发布:新浪微博个性域名在哪 编辑:程序博客网 时间:2024/06/15 23:19

ai 表示从 i 到根的边的长度。对于每个点维护 disti 表示从根到 i 的路径, mindisti 表示 i 的子树中 distj+aj 的最小值。
然后对于询问 (u,v) 分类:
如果 uv 的祖先,由于权值都是正整数,答案为distvdistu
否则答案为mindistudistu+distv
distmindistdfs 序+线段树维护就可以了。

代码

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;inline char nc(){    static char buf[100000],*p1=buf,*p2=buf;    if(p1==p2){        p2=(p1=buf)+fread(buf,1,100000,stdin);        if(p1==p2)return EOF;    }    return *p1++;}inline void Read(int& x){    char c=nc();    for(;c<'0'||c>'9';c=nc());    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());}#define N 200010#define ll long longstruct Edge{    int f,t,nx,w;}e[N<<1];ll c[N<<2],p[N<<2],Pa[N],c2[N<<2];int d[N],Top[N],Son[N],l[N],r[N],s[N],f[N],w[N],x,y,z;int h[N],Num;int i,j,k,n,m,Q,a[N],L;inline void Dfs1(int x,int y){    d[x]=++y;l[x]=++Num;s[x]=1;w[Num]=x;    for(int i=h[x];i;i=e[i].nx){        Pa[e[i].t]=Pa[x]+e[i].w;        Dfs1(e[i].t,y);        s[x]+=s[e[i].t];        if(s[e[i].t]>s[Son[x]])Son[x]=e[i].t;    }    r[x]=Num;}inline void Dfs2(int x,int y){    Top[x]=y;    if(Son[x])Dfs2(Son[x],y);    for(int i=h[x];i;i=e[i].nx)    if(e[i].t!=Son[x])Dfs2(e[i].t,e[i].t);}inline ll Min(ll x,ll y){    return x<y?x:y;}inline void Up(int x){    c[x]=Min(c[x<<1],c[x<<1|1]);}inline void Down(int x){    if(p[x]){        c[x<<1]+=p[x];c2[x<<1]+=p[x];p[x<<1]+=p[x];        c[x<<1|1]+=p[x];c2[x<<1|1]+=p[x];p[x<<1|1]+=p[x];        p[x]=0;    }}inline void Update1(int x,int l,int r,int y,int z){    if(l==r){        c[x]+=z;        return;    }    Down(x);    int Mid=l+r>>1;    if(y<=Mid)Update1(x<<1,l,Mid,y,z);else Update1(x<<1|1,Mid+1,r,y,z);    Up(x);}inline void Update2(int x,int l,int r,int L,int R,int y){    if(l>R||r<L)return;    if(l>=L&&r<=R){        c[x]+=y;c2[x]+=y;p[x]+=y;        return;    }    Down(x);    int Mid=l+r>>1;    Update2(x<<1,l,Mid,L,R,y);Update2(x<<1|1,Mid+1,r,L,R,y);    Up(x);}inline ll Query(int x,int l,int r,int L,int R){    if(l>R||r<L)return 1e18;    if(l>=L&&r<=R)return c[x];    Down(x);    int Mid=l+r>>1;    return Min(Query(x<<1,l,Mid,L,R),Query(x<<1|1,Mid+1,r,L,R));}inline ll Query2(int x,int l,int r,int y){    if(l==r)return c2[x];    Down(x);    int Mid=l+r>>1;    if(y<=Mid)return Query2(x<<1,l,Mid,y);    return Query2(x<<1|1,Mid+1,r,y);}inline void Build(int x,int l,int r){    if(l==r){        c[x]=Pa[w[l]]+a[w[l]];        c2[x]=Pa[w[l]];        return;    }    int Mid=l+r>>1;    Build(x<<1,l,Mid);Build(x<<1|1,Mid+1,r);    Up(x);}inline int Lca(int x,int y){    while(Top[x]!=Top[y])    if(d[Top[x]]>d[Top[y]])x=f[Top[x]];else y=f[Top[y]];    return d[x]>d[y]?y:x;}int main(){    Read(n);Read(Q);    for(i=1;i<n;i++)Read(e[i].f),Read(e[i].t),Read(e[i].w),e[i].nx=h[e[i].f],h[e[i].f]=i,f[e[i].t]=e[i].f;    for(i=1;i<n;i++)Read(e[i+n-1].f),Read(e[i+n-1].t),Read(a[e[i+n-1].f]);    Num=0;Dfs1(1,0);Dfs2(1,1);    Build(1,1,n);    while(Q--){        Read(k);Read(x);Read(y);        if(k==1){            if(x>=n)Update1(1,1,n,l[e[x].f],y-a[e[x].f]),a[e[x].f]=y;else            Update2(1,1,n,l[e[x].t],r[e[x].t],y-e[x].w),e[x].w=y;        }else{            L=Lca(x,y);            if(L==x)printf("%I64d\n",Query2(1,1,n,l[y])-Query2(1,1,n,l[x]));else            printf("%I64d\n",Query(1,1,n,l[x],r[x])-Query2(1,1,n,l[x])+Query2(1,1,n,l[y]));        }    }    return 0;}
原创粉丝点击