Luogu P5642 Artificial emotion (emotion)

Question link

Click to open link

Question solution

Consider how to calculate

f

(

U

)

f(U)

f(U), I don’t know how to think of the following solution

One trick is to hang the path in

l

c

a

lca

lca on

we order

f

u

f_{u}

fu? means completely included in

u

u

the largest independent set of paths in the subtree of u
Consider transferring, remember

s

u

m

u

=

v

s

o

n

(

u

)

f

v

sum_{u}=\sum\limits_{v\in son(u)}f_v

sumu?=v∈son(u)∑?fv?

  1. if

    u

    u

    u is not on any of the selected paths

    f

    u

    =

    s

    u

    m

    u

    f_u=sum_u

    fu?=sumu?

  2. u

    u

    The weight value of u is

    w

    w

    path of w

    x

    y

    x\to y

    x→y up
    Consider for

    x

    u

    x\to u

    x→u and

    y

    u

    y\to u

    The paths of y→u are considered separately, and the formula is given first:

    f

    u

    =

    s

    u

    m

    u

    +

    w

    ?

    q

    p

    a

    t

    h

    (

    x

    ,

    u

    )

    or

    q

    p

    a

    t

    h

    (

    y

    ,

    u

    )

    (

    f

    q

    ?

    s

    u

    m

    q

    )

    f_u=sum_u + w-\sum\limits_{q\in path(x,u)\;or\;q\in path(y,u)}(f_q-sum_q)

    fu?=sumu? + w?q∈path(x,u) or q∈path(y,u)∑?(fqsumq?)
    need to subtract

    f

    q

    ?

    s

    u

    m

    q

    f_q-sum_q

    fqsumq? because

    p

    a

    t

    h

    (

    x

    ,

    y

    )

    path(x,y)

    No point on path(x,y) can be selected on other paths, and our state naturally fits

    f

    q

    ?

    s

    u

    m

    q

    f_q-sum_q

    fqsumq? Yes

    q

    q

    q is not here

    q

    q

    q Number of solutions on the subtree path

The above things can be used

B

I

T

BIT

BIT maintenance, specifically, it needs to implement single point addition and chain search, and because of the unique structure of the traversal tree, we can turn it into subtree addition and single point search

At the same time we need another array

g

u

g_u

gu? means

u

u

u The largest independent set of paths outside the subtree
Continuing to consider classification transfer, we consider using

g

u

g_u

Derivation of the answer for gu?

g

v

(

v

s

o

n

(

u

)

)

g_v(v\in son(u))

The answer for gv?(v∈son(u))

  1. u

    u

    u is not on any path

    g

    v

    =

    g

    u

    +

    s

    u

    m

    u

    ?

    f

    v

    g_v=g_u + sum_u-f_v

    gv?=gu? + sumufv?

  2. u

    u

    The weight value of u is

    w

    w

    path of w

    x

    y

    x\to y

    on x→y,

    x

    y

    x\to y

    x→y does not pass

    v

    v

    v
    make

    x

    ,

    y

    x,y

    x,y

    l

    c

    a

    lca

    lca is

    h

    h

    h
    It is not difficult to come up with this formula:

    g

    v

    =

    g

    h

    +

    w

    +

    s

    u

    m

    h

    ?

    q

    p

    a

    t

    h

    (

    x

    ,

    y

    )

    (

    f

    q

    ?

    s

    u

    m

    q

    )

    ?

    f

    v

    g_v=g_h + w + sum_h-\sum\limits_{q\in path(x,y)}(f_q-sum_q)-f_v

    gv?=gh? + w + sumhq∈path(x,y)∑?(fqsumq?)?fv?

The things above can flatten the tree into

d

f

s

dfs

dfs order, and then do the line segment tree, pay attention to special considerations

l

c

a

=

u

lca=u

lca=u case

Finally, you can consider calculating the answer
I marked the violent calculation with comments in the program, and then optimized the violent calculation. This is not too difficult, just pay attention to some details.

time complexity

O

(

n

l

o

g

n

)

O(nlogn)

O(nlogn)

#include <bits/stdc + + .h>
#define int long long
#define lowbit(x) x & amp;-x
#define pb push_back
using namespace std;
const int N=300100,P=998244353;
struct Lines{<!-- --> int u,v,w;};
int n,m,ans;
int depth[N],up[N][20],siz[N];
int Ldfn[N],Rdfn[N],dfs_clock;
int f[N],sum[N];//f[u]: The sum of the weights of disjoint paths in the u subtree
int g[N];//g[u]: The sum of the weights of non-intersecting paths outside the u subtree
int e[N<<1],ne[N<<1],h[N],idx;
vector<int> G[N];
vector<Lines> ln[N];
inline int read(){<!-- -->
    int FF=0,RR=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
    for(;isdigit(ch);ch=getchar()) FF=(FF<<1) + (FF<<3) + ch-48;
    return FF*RR;
}
void predfs(int u,int fa){<!-- -->
    depth[u]=depth[fa] + 1;
    Ldfn[u]= + + dfs_clock,up[u][0]=fa;
    for(int i=h[u];~i;i=ne[i]) if(e[i]!=fa) G[u].pb(e[i]),predfs(e[i], u);
    Rdfn[u]=dfs_clock;
}
int get_lca(int x,int y){<!-- -->
    if(depth[x]>depth[y]) swap(x,y);
    for(int i=18;i>=0;i--) if(depth[up[y][i]]>=depth[x]) y=up[y][i];
    if(x==y) return x;
    for(int i=18;i>=0;i--) if(up[x][i]!=up[y][i]) x=up[x][i],y=up[y ][i];
    return up[x][0];
}
struct BIT{<!-- -->
    int tr[N];
    void inc(int x,int v){<!-- --> for(;x<=n;x + =lowbit(x)) tr[x] + =v;}
    void add(int l,int r,int v){<!-- --> inc(l,v),inc(r + 1,-v);}
    int ask(int x){<!-- -->
        int res=0;
        for(;x;x-=lowbit(x)) res + =tr[x];
        return res;
    }
}BIT;
struct SGT{<!-- -->
    int seg[N<<2];
    void modify(int l,int r,int x,int pos,int v){<!-- -->
        if(l==r){<!-- --> seg[x]=max(seg[x],v);return;}
        int mid=(l + r)>>1;
        if(mid>=pos) modify(l,mid,x<<1,pos,v);
        else modify(mid + 1,r,x<<1^1,pos,v);
        seg[x]=max(seg[x<<1],seg[x<<1^1]);
    }
    int query(int l,int r,int x,int L,int R){<!-- -->
        if(L<=l & amp; & amp;r<=R) return seg[x];
        int mid=(l + r)>>1;
        if(mid>=L & amp; & amp;mid<R) return max(query(l,mid,x<<1,L,R),query(mid + 1,r,x<<1^1, L,R));
        if(mid>=L) return query(l,mid,x<<1,L,R);
        return query(mid + 1,r,x<<1^1,L,R);
    }
    void upd(int pos,int v){<!-- --> modify(1,n,1,pos,v);}
    int ask(int l1,int r1,int l2,int r2){<!-- -->
        int ret=0;
        if(l1<l2) ret=max(ret,query(1,n,1,l1,l2-1));
        if(r2<r1) ret=max(ret,query(1,n,1,r2 + 1,r1));
        return ret;
    }
}sg;
void calc_f(int u){<!-- -->
    for(int v:G[u]) calc_f(v),sum[u] + =f[v];
    //u is not on the path
    f[u]=sum[u];
    //u is on the path
    for(auto & amp;E:ln[u]){<!-- -->
        E.w + =sum[u]-BIT.ask(Ldfn[E.u])-BIT.ask(Ldfn[E.v]);
        f[u]=max(f[u],E.w);
        //Single point addition + chain sum + properties of dfs -> subtree addition, single point check, single log
    }
    BIT.add(Ldfn[u],Rdfn[u],f[u]-sum[u]);
}
void calc_g(int u){<!-- -->
    sort(ln[u].begin(),ln[u].end(),[ & amp;](Lines x,Lines y){<!-- --> return x.w>y.w;});
    for(int v:G[u]){<!-- -->
        g[v]=g[u] + sum[u]-f[v];
        for(auto E:ln[u])
            if(get_lca(E.u,v)!=v & amp; & amp;get_lca(E.v,v)!=v){<!-- -->//u,v does not have one end in the subtree of v
                g[v]=max(g[v],E.w + g[u]-f[v]);break;
            }
        g[v]=max(g[v],sg.ask(Ldfn[u],Rdfn[u],Ldfn[v],Rdfn[v])-f[v]);
    }
    for(auto E:ln[u]) sg.upd(Ldfn[E.u],E.w + g[u]),sg.upd(Ldfn[E.v],E.w + g[u]);
    for(int v:G[u]) calc_g(v);
}
void calc_ans(int u){<!-- -->
    int res=0;
    for(int v:G[u]) calc_ans(v),res=(res + siz[u]*siz[v])%P,siz[u] + =siz[v];
    siz[u] + + ;
    ans-=(g[u] + f[u])%P*(2*res + 2*siz[u]-1)%P;
    res=(2*(siz[u]-1)*(n-siz[u])%P + 2*res + 2*n-1)%P;
    ans + =(f[u]-sum[u])%P*res%P;
    ans=(ans%P + P)%P;
}
void add(int x,int y){<!-- --> e[idx]=y,ne[idx]=h[x],h[x]=idx + + ;}
// int get_sum(int x,int y){<!-- -->
// int lca=get_lca(x,y),res=0;
// while(x!=lca) res + =f[x]-sum[x],x=up[x][0];
// while(y!=lca) res + =f[y]-sum[y],y=up[y][0];
// res + =f[lca]-sum[lca];
// return res;
// }
signed main(){<!-- -->
    n=read(),m=read();
    memset(h,-1,sizeof(h));
    for(int i=1;i<n;i + + ){<!-- -->
        int x=read(),y=read();
        add(x,y),add(y,x);
    }
    predfs(1,-1);
    for(int j=1;j<=18;j + + ) for(int i=1;i<=n;i + + ) up[i][j]=up[up[i][j-1 ]][j-1];
    for(int i=1;i<=m;i + + ){<!-- -->
        int u=read(),v=read(),w=read();
        int lca=get_lca(u,v);
        ln[lca].pb({<!-- -->u,v,w});
    }
    calc_f(1),calc_g(1),calc_ans(1);
    ans=(ans + f[1]%P*n%P*n)%P;
    // for(int i=1;i<=n;i + + ) for(int j=1;j<=n;j + + )
    // ans + =f[1]-g[get_lca(i,j)]-f[get_lca(i,j)] + get_sum(i,j);
    printf("%lld\
",ans);
    fprintf(stderr,"%d ms\
",int64_t(1e3*clock()/CLOCKS_PER_SEC));
    return 0;
}