G blood pressure game (the same height point in the tree goes to the root at the same time, lca)

Question: https://ac.nowcoder.com/acm/contest/5278/G

Topic: Given a tree of n points, each node has a weight, and the weight of each node will move up by a height every time. When the weight of a node is greater than 1, this node will have weight on this node The value is reduced by one, until it moves to the root of the tree, and the final weight is added to the answer. Finally, what is the sum of this answer?

Analysis: We know that the weight combination (path combination) in the process of running toward the root at different heights and the process of weight reduction do not affect each other. This prompts us to divide the nodes of the same height. A group of the same height to analyze;

   The most complicated case is the merge of paths. The merge of each path must be the merger of the two LCA or the merger of the LCA of the two. . . , We have to find a way to get all the lca from this group? Because after finding out, we can directly simulate the answer;

   And there is a conclusion that all the lca of the nodes of the same height are in the order of the dfs of each node, and the lca of the adjacent nodes after sorting is the junction point through which these nodes will pass to run. The junction point will not exceed this height node number -1;

   When processing, we only need to deal with non-zero points. For two adjacent nodes x, y to lca, there will be no combination between them, then the contribution of x to lca is his current weight-(x Difference to the depth of lca), y is the same

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
const int M=2e5+5;
vector<int>g[M];
int sz[M],deep[M],dfn[M],cnt,f[M],tp[M],son[M],id[M],fa[M];
ll a[M],val[M];
struct node{
    int son1,son2,p;
}same[M];
void dfs1(int u,int ff){
    sz[u]=1,deep[u]=deep[ff]+1,dfn[u]=++cnt,fa[u]=ff;
    for(auto v:g[u]){
        if(v!=ff){
            dfs1(v,u);
            sz[u]+=sz[v];
            if(sz[son[u]]<sz[v])
                son[u]=v;
        }
    }
}
void dfs2(int u,int top){
    tp[u]=top;
    if(son[u])
        dfs2(son[u],top);
    for(auto v:g[u]){
        if(v!=fa[u]&&v!=son[u])
            dfs2(v,v);
    }
}
int LCA(int x,int y){
    while(tp[x]!=tp[y]){
        if(deep[tp[x]]>deep[tp[y]])
            x=fa[tp[x]];
        else
            y=fa[tp[y]];
    }
    return deep[x]>deep[y]?y:x;
}
int find(int x){
    return f[x]==x?x:f[x]=find(f[x]);
}
bool cmp1(int x,int y){
    if(deep[x]==deep[y])
        return dfn[x]<dfn[y];
    return deep[x]>deep[y];
}
bool cmp2(node x,node y){
    if(deep[x.p]==deep[y.p])
        return dfn[x.p]<dfn[y.p];
    return deep[x.p]>deep[y.p];
}
int main(){
    int n,rt;
    scanf("%d%d",&n,&rt);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    for(int u,v,i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        g[u].pb(v);
        g[v].pb(u);
    }
    dfs1(rt,0);
    dfs2(rt,rt);
    int m=0;
    for(int i=1;i<=n;i++){
        if(a[i])
            id[++m]=i;
    }
    sort(id+1,id+1+m,cmp1);
    ll ans=0;
    for(int fir=1;fir<=m;fir++){
        int sec=fir;
        while(sec<=m&&deep[id[fir]]==deep[id[sec]])
            sec++;
        sec--;
        for(int i=fir;i<=sec;i++)
            f[id[i]]=id[i],val[id[i]]=a[id[i]];
        if(fir==sec){
            ans+=max(1ll,a[id[fir]]-deep[id[fir]]);
            continue;
        }
        int tot=0;
        for(int i=fir;i<sec;i++){
            int lca=LCA(id[i],id[i+1]);
            same[++tot].p=lca;
            same[tot].son1=id[i];
            same[tot].son2=id[i+1];
            f[lca]=lca;
            val[lca]=0;
        }
        sort(same+1,same+1+tot,cmp2);
        for(int i=1;i<=tot;i++){
            int x=find(same[i].son1),y=find(same[i].son2);
            ll val1=0,val2=0;
            if(x!=same[i].p)
                val1=max(1ll,val[x]-(deep[x]-deep[same[i].p]));
            if(y!=same[i].p)
                val2=max(1ll,val[y]-(deep[y]-deep[same[i].p]));
            val[same[i].p]+=val1+val2;
            f[x]=f[y]=same[i].p;

        }
        ans+=max(1ll,val[same[tot].p]-deep[same[tot].p]);
        fir=sec;
    }
    printf("%lld",ans);
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/starve/p/12735709.html