[Codeforces 600E] Lomsat gelral

[题目链接]

          https://codeforces.com/contest/600/problem/E

[算法]

        对于每一个点建立一棵线段树 , 维护当前点的子树中每个点的出现次数

        可以通过深度优先遍历从下到上进行线段树合并

        时间复杂度 : O(NlogN)

[代码]

        

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
#define MAXP 5000005
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

struct edge
{
        int to , nxt;
} e[MAXN << 1];

int tot , n , m;
int head[MAXN] , rt[MAXN] , c[MAXN];
ll ans[MAXN];

struct Segment_Tree
{
        int sz;
        Segment_Tree()
        {
                sz = 0;
        }
        struct Node
        {
                int lc , rc;
                int mx;
                ll cnt;        
        }    a[MAXP];
        inline void update(int x)
        {
                a[x].mx = max(a[a[x].lc].mx , a[a[x].rc].mx);
                if (a[a[x].lc].mx > a[a[x].rc].mx) a[x].cnt = a[a[x].lc].cnt;
                else if (a[a[x].rc].mx > a[a[x].lc].mx) a[x].cnt = a[a[x].rc].cnt;
                else a[x].cnt = a[a[x].lc].cnt + a[a[x].rc].cnt;
        }
        inline void modify(int &now , int l , int r , int x , int value)
        {
                if (!now) now = ++sz;
                if (l == r)
                {
                        a[now].mx += value;
                        a[now].cnt = l;
                        return;
                }
                int mid = (l + r) >> 1;
                if (mid >= x) modify(a[now].lc , l , mid , x , value);
                else modify(a[now].rc , mid + 1 , r , x , value);
                update(now);
        }
        inline int merge(int x , int y , int l , int r)
        {
                if (x == 0 || y == 0) return x + y;
                if (l == r)
                {
                        a[x].mx += a[y].mx;
                        a[x].cnt = l;
                        return x;
                }
                int mid = (l + r) >> 1;
                a[x].lc = merge(a[x].lc , a[y].lc , l , mid);
                a[x].rc = merge(a[x].rc , a[y].rc , mid + 1 , r);
                update(x);
                return x;
        }
        inline ll getans(int u)
        {
                return a[rt[u]].cnt;
        }
} SGT;

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
inline void addedge(int u , int v)
{
        ++tot;
        e[tot] = (edge){v , head[u]};
        head[u] = tot;
}
inline void calc(int u , int father)
{
        for (int i = head[u]; i; i = e[i].nxt)
        {
                int v = e[i].to;
                if (v == father) continue;
                calc(v , u);
                rt[u] = SGT.merge(rt[u] , rt[v] , 1 , n);        
        }        
        ans[u] = SGT.getans(u);
}

int main()
{
        
        read(n);
        for (int i = 1; i <= n; i++) 
        {
                read(c[i]);
                SGT.modify(rt[i] , 1 , n , c[i] , 1);
        }
        for (int i = 1; i < n; i++)
        {
                int x , y;
                read(x); read(y);
                addedge(x , y);
                addedge(y , x);
        }
        calc(1 , 0);
        for (int i = 1; i <= n; i++) printf("%lld " , ans[i]);
        printf("\n");
        
        return 0;
}

猜你喜欢

转载自www.cnblogs.com/evenbao/p/10222878.html