CodeForces-600E Lomsat gelral(树上DSU)

题意

给定一个 n 个节点的树,对于每个子树,输出子树中出现次数最多的节点编号之和。(次数最多的编号有多个节点都要统计进去)。
1 n 10 5

思路

无疑仍是树上 d s u ,考虑到需要维护节点出现次数最多的编号和,所以实时维护一个数组 c n t 保存每种编号出现的次数,然后再用两个变量分别保存最多出现次数和答案即可。由于树上 d s u 有一个性质,每次 u p d a t e ( 1 ) 的时候都刚好把所有信息都清除,所以可以将上述的两个变量直接还原为 0 ,然后将 c n t 上减即可,不用维护其他信息。

代码

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
#define lowbit(x) ((x)&-(x))
#define N 100003
typedef long long LL;
using namespace std;
template<const int maxn,const int maxm>struct Linked_list
{
    int head[maxn],to[maxm],nxt[maxm],tot;
    void clear(){memset(head,-1,sizeof(head));tot=0;}
    void add(int u,int v){to[++tot]=v,nxt[tot]=head[u],head[u]=tot;}
    #define EOR(i,G,u) for(int i=G.head[u];~i;i=G.nxt[i])
};
Linked_list<N,N<<1>G;
int L[N],R[N],sz[N],son[N],ori[N],cnt[N],col[N],ord,maxocc,n;
LL res[N],sum;

void dfs(int u,int f)
{
    L[u]=++ord,sz[u]=1,son[u]=0,ori[ord]=u;
    EOR(i,G,u)
    {
        int v=G.to[i];
        if(v==f)continue;
        dfs(v,u);
        sz[u]+=sz[v];
        if(sz[v]>sz[son[u]])son[u]=v;
    }
    R[u]=ord;
}
void add(int L,int R,int val)
{
    FOR(i,L,R)
    {
        cnt[col[ori[i]]]+=val;
        if(cnt[col[ori[i]]]>maxocc)maxocc++,sum=col[ori[i]];
        else if(cnt[col[ori[i]]]==maxocc)sum+=col[ori[i]];
    }
}
void dsu(int u,int f)
{
    EOR(i,G,u)
    {
        int v=G.to[i];
        if(v==f||v==son[u])continue;
        maxocc=sum=0;
        dsu(v,u);
        add(L[v],R[v],-1);
    }
    maxocc=sum=0;
    if(son[u])dsu(son[u],u);
    EOR(i,G,u)
    {
        int v=G.to[i];
        if(v==f||v==son[u])continue;
        add(L[v],R[v],1);
    }
    add(L[u],L[u],1);
    res[u]=sum;
}
void clear()
{
    G.clear();
    memset(cnt,0,sizeof(cnt));
    maxocc=sum=ord=0;
}

int main()
{
    while(~scanf("%d",&n))
    {
        clear();
        FOR(i,1,n)scanf("%d",&col[i]);
        FOR(i,1,n-1)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            G.add(u,v);
            G.add(v,u);
        }
        dfs(1,0);
        dsu(1,0);
        FOR(i,1,n-1)printf("%lld ",res[i]);
        printf("%lld\n",res[n]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Paulliant/article/details/81805308
今日推荐