(题面来自luogu)
一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和。
ci <= n <= 1e5
裸题。统计时先扫一遍得到出现次数最大值,然后再扫一遍看哪个颜色的出现次数与mxCnt相等。注意用一个bool数组判重,清空轻儿子贡献时要顺手把bool数组也打成false。(这是错的,请看下一份代码)
代码:
#include
#include
#include
#define maxn 100010
using namespace std;
template
void read(T &x) {
x = 0;
char ch = getchar();
while (!isdigit(ch))
ch = getchar();
while (isdigit(ch))
x = x * 10 + (ch ^ 48), ch = getchar();
}
int n;
int head[maxn], top;
struct E {
int to, nxt;
} edge[maxn << 1];
inline void insert(int u, int v) {
edge[++top] = (E) {v, head[u]};
head[u] = top;
}
int son[maxn], size[maxn];
long long ans[maxn];
void dfs1(int u, int pre) {
size[u] = 1;
for (int i = head[u]; i; i = edge[i].nxt) {
int v = edge[i].to;
if (v == pre) continue;
dfs1(v, u);
size[u] += size[v];
if (size[v] > size[son[u]])
son[u] = v;
}
return;
}
int color[maxn], cnt[maxn], sum;
int curSon, mxCnt;
bool vis[maxn];
void calc(int u, int pre, bool op) {
op ? (++cnt[color[u]], mxCnt = max(mxCnt, cnt[color[u]])) : (--cnt[color[u]], vis[color[u]] = false);
for (int i = head[u]; i; i = edge[i].nxt) {
int v = edge[i].to;
if (v == pre || v == curSon)
continue;
calc(v, u, op);
}
}
void stats(int u, int pre) {
if (cnt[color[u]] == mxCnt && !vis[color[u]])
sum += color[u], vis[color[u]] = true;
for (int i = head[u]; i; i = edge[i].nxt) {
int v = edge[i].to;
if (v != pre)
stats(v, u);
}
return;
}
void dsu(int u, int pre, bool op) {
for (int i = head[u]; i; i = edge[i].nxt) {
int v = edge[i].to;
if (v == pre || v == son[u])
continue;
dsu(v, u, 0);
}
if (son[u])
dsu(son[u], u, 1), curSon = son[u];
mxCnt = 0;
calc(u, pre, 1);
stats(u, pre);
ans[u] = sum;
curSon = 0;
if (!op) {
sum = 0;
calc(u, pre, 0);
}
}
int main() {
read(n);
for (int i = 1; i <= n; ++i)
read(color[i]);
int u, v;
for (int i = 1; i < n; ++i) {
read(u), read(v);
insert(v, u), insert(u, v);
}
dfs1(1, 0);
dsu(1, 0, 1);
for (int i = 1; i <= n; ++i)
printf("%I64d ", ans[i]);
return 0;
}
(交这个题的时候cf炸了……才不是因为我TLE呢
--------------------------
然而果然出了锅,昨天CF评测机大概是被这个弱智错误笑死的……
重测了下,上面那份代码是错的,原因是没有考虑重儿子内的最大出现次数。然而原思路越改越复杂,后来想了想,每遍历到重复的颜色其出现次数都会+1,因此不用判重,从每个点统计时扫一遍就好了。
代码:
手机扫一扫
移动阅读更方便
你可能感兴趣的文章