例题:给出一棵树,求出每个节点的子树中出现次数最多的颜色的编号和

这个东西的时间复杂度竟然是nlogn的。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#define ll long long
#define llu unsigned ll
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int maxn=100100;
int head[maxn],ver[maxn<<1],nt[maxn<<1];
int c[maxn],cnt[maxn],si[maxn],son[maxn],hson;
int n,tot=0,maxx;
ll sum=0,ans[maxn];

void add(int x,int y)
{
    ver[++tot]=y,nt[tot]=head[x],head[x]=tot;
}

void dfs1(int x,int fa)
{
    int max_son=0;
    si[x]=1;
    for(int i=head[x];i;i=nt[i])
    {
        int y=ver[i];
        if(y==fa) continue;
        dfs1(y,x);
        si[x]+=si[y];
        if(si[y]>max_son) max_son=si[y],son[x]=y;
    }
}

void in(int x,int fa,int val)
{
    cnt[c[x]]+=val;
    if(cnt[c[x]]>maxx) maxx=cnt[c[x]],sum=c[x];
    else if(cnt[c[x]]==maxx) sum=sum+(ll)c[x];
    for(int i=head[x];i;i=nt[i])
    {
        int y=ver[i];
        if(y==fa||y==hson) continue;
        in(y,x,val);
    }
}

void dfs2(int x,int fa,int flag)
{
    for(int i=head[x];i;i=nt[i])
    {
        int y=ver[i];
        if(y==fa||y==son[x]) continue;
        dfs2(y,x,0);
    }
    if(son[x])
    {
        dfs2(son[x],x,1);
        hson=son[x];
    }
    in(x,fa,1);
    hson=0;
    ans[x]=sum;
    if(!flag) in(x,fa,-1),sum=0,maxx=0;
}

int main(void)
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&c[i]);
    int x,y;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs1(1,0);
    dfs2(1,0,0);
    for(int i=1;i<=n;i++)
        printf("%lld ",ans[i]);
    return 0;
}