【CF600E】Lomsat gelral

【CF600E】Lomsat gelral

题面

给你一颗\(n\)个节点的树,每个节点都有一种颜色,\(m\)次询问,每次询问求每个子树中出现次数最多的颜色(们)的编号之和。

其中\(n\leq10^5,m\leq10^5\)

题解

\(dsu\;on\;tree\)板子题

不会的推荐看\(gsy\)的博客

其实还是挺简单的

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (ch != '-' && (ch > '9' || ch < '0')) ch = getchar();
    if (ch == '-') w = -1 , ch = getchar();
    while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
    return w * data;
} 
#define MAX_N 100005 
typedef long long ll; 
struct Graph { int to, next; } e[MAX_N << 1]; 
int fir[MAX_N], e_cnt = 0; 
void clearGraph() { memset(fir, -1, sizeof(fir)); e_cnt = 0; } 
void Add_Edge(int u, int v) { 
    e[e_cnt].to = v, e[e_cnt].next = fir[u], fir[u] = e_cnt++; 
} 
int size[MAX_N], son[MAX_N]; 
ll ans[MAX_N], sum[MAX_N]; 
int num[MAX_N], top, c[MAX_N], N; 
bool vis[MAX_N]; 
void dfs1(int x, int f) { 
    size[x] = 1; 
    for (int i = fir[x]; ~i; i = e[i].next) { 
        int v = e[i].to; 
        if (v == f) continue; 
        dfs1(v, x); 
        size[x] += size[v]; 
        if (size[son[x]] < size[v]) son[x] = v; 
    } 
} 
void update(int x, int f, int opt) { 
    sum[num[c[x]]] -= c[x]; 
    num[c[x]] += opt; 
    sum[num[c[x]]] += c[x]; 
    if (sum[top + 1]) ++top; 
    if (!sum[top]) --top; 
    for (int i = fir[x]; ~i; i = e[i].next) { 
        int v = e[i].to; 
        if (v == f || vis[v]) continue; 
        update(v, x, opt);  
    } 
} 
void dfs2(int x, int f, bool hs) { 
    for (int i = fir[x]; ~i; i = e[i].next) { 
        int v = e[i].to; 
        if (v == f || v == son[x]) continue; 
        dfs2(v, x, 0); 
    } 
    if (son[x]) dfs2(son[x], x, 1), vis[son[x]] = 1; 
    update(x, f, 1); vis[son[x]] = 0; 
    ans[x] = sum[top]; 
    if (!hs) update(x, f, -1); 
} 
int main() { 
    clearGraph(); 
    N = gi(); 
    for (int i = 1; i <= N; i++) c[i] = gi(); 
    for (int i = 1; i < N; i++) { 
        int u = gi(), v = gi(); 
        Add_Edge(u, v); Add_Edge(v, u); 
    } 
    dfs1(1, 0); 
    dfs2(1, 0, 1); 
    for (int i = 1; i <= N; i++) printf("%I64d ", ans[i]); 
    printf("\n"); 
    return 0; 
} 
posted @ 2019-01-26 22:29  heyujun  阅读(253)  评论(0编辑  收藏  举报