题意翻译
一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和。
线段树合并板子题,没啥难度,注意开long long
不过这题$dsu$ $on$ $tree$确实更快
代码:
1 #include<iostream>
2 #include<cstdio>
3 #define ls ch[node][0]
4 #define rs ch[node][1]
5 #define M 100010
6 using namespace std;
7 int n,m,num,cnt;
8 int head[M],rt[M],co[M];
9 int ch[M<<7][2],v1[M<<7];
10 long long v2[M<<7],ans[M];
11 struct point{int to,next;}e[M<<1];
12 void add(int from,int to) {
13 e[++num].next=head[from];
14 e[num].to=to;
15 head[from]=num;
16 }
17 void update(int node) {
18 if(v1[ls]==v1[rs]) {
19 v1[node]=v1[ls];v2[node]=v2[ls]+v2[rs];
20 }
21 else{
22 if(v1[ls]>v1[rs]) v1[node]=v1[ls],v2[node]=v2[ls];
23 else v1[node]=v1[rs],v2[node]=v2[rs];
24 }
25 }
26 void insert(int &node,int l,int r,int x) {
27 if(!node) node=++cnt;
28 if(l==r) {
29 v1[node]=1,v2[node]=x;return;
30 }int mid=(l+r)/2;
31 if(x<=mid) insert(ls,l,mid,x);
32 else insert(rs,mid+1,r,x);
33 update(node);
34 }
35 int merge(int x,int y,int l,int r) {
36 if(!x||!y) return x+y;
37 int node=++cnt;
38 if(l==r) {
39 v1[node]=v1[x]+v1[y];v2[node]=l;return node;
40 }
41 int mid=(l+r)/2;
42 ch[node][0]=merge(ch[x][0],ch[y][0],l,mid);
43 ch[node][1]=merge(ch[x][1],ch[y][1],mid+1,r);
44 update(node);return node;
45 }
46 void dfs(int x,int fa) {
47 insert(rt[x],1,n,co[x]);
48 for(int i=head[x];i;i=e[i].next) {
49 int to=e[i].to;
50 if(to==fa) continue;
51 dfs(to,x);
52 rt[x]=merge(rt[x],rt[to],1,n);
53 }
54 ans[x]=v2[rt[x]];
55 }
56 int main() {
57 scanf("%d",&n);
58 for(int i=1;i<=n;i++) scanf("%d",&co[i]);
59 for(int i=1;i<n;i++) {
60 int x,y;scanf("%d%d",&x,&y);
61 add(x,y),add(y,x);
62 }
63 dfs(1,0);
64 for(int i=1;i<=n;i++) printf("%lld ",ans[i]);
65 return 0;
66 }