You are given a rooted tree with root in vertex 1. Each vertex is coloured in some colour.

Let's call colour c dominating in the subtree of vertex v if there are no other colours that appear in the subtree of vertex v more times than colour c. So it's possible that two or more colours will be dominating in the subtree of some vertex.

The subtree of vertex v is the vertex v and all other vertices that contains vertex v in each path to the root.

For each vertex v find the sum of all dominating colours in the subtree of vertex v.

Input

The first line contains integer n (1 ≤ n ≤ 105) — the number of vertices in the tree.

The second line contains n integers ci (1 ≤ ci ≤ n), ci — the colour of the i-th vertex.

Each of the next n - 1 lines contains two integers xj, yj (1 ≤ xj, yj ≤ n) — the edge of the tree. The first vertex is the root of the tree.

Output

Print n integers — the sums of dominating colours for each vertex.

Examples
input

Copy
4
1 2 3 4
1 2
2 3
2 4
output

Copy
10 9 3 4
input

Copy
15
1 2 3 1 2 3 3 1 1 3 2 2 1 2 3
1 2
1 3
1 4
1 14
1 15
2 5
2 6
2 7
3 8
3 9
3 10
4 11
4 12
4 13
output

Copy
6 5 4 3 2 3 3 1 1 3 2 2 1 2 3

思路:

对每个点建线段树在线段树上当前点的权值下标+1,每个点与父节点进行线段树合并,这样对树dfs一遍就可以求出所有的值了。

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mid ll m = (l + r) >> 1
const ll M = 1e5 + ; struct node{
ll ans,sum;
}tr[M*]; struct node1{
ll to,next;
}e[M<<];
ll cnt,head[M],idx,ls[M*],rs[M*],root[M],a[M],ans[M]; void add(ll u,ll v){
e[++cnt].to = v;e[cnt].next = head[u];head[u] = cnt;
} void pushup(ll rt){
if(tr[ls[rt]].sum > tr[rs[rt]].sum){
tr[rt].sum = tr[ls[rt]].sum;
tr[rt].ans = tr[ls[rt]].ans;
}
else if(tr[ls[rt]].sum == tr[rs[rt]].sum){
tr[rt].sum = tr[ls[rt]].sum;
tr[rt].ans = tr[rs[rt]].ans + tr[ls[rt]].ans;
}
else{
tr[rt].sum = tr[rs[rt]].sum;
tr[rt].ans = tr[rs[rt]].ans;
}
} void update(ll p,ll c,ll l,ll r,ll &rt){
if(!rt) rt = ++idx;
if(l == r){
tr[rt].sum += c;
tr[rt].ans = l;
return ;
}
mid;
if(p <= m) update(p,c,l,m,ls[rt]);
else update(p,c,m+,r,rs[rt]);
pushup(rt);
} ll Merge(ll x,ll y,ll l,ll r){
if(!x) return y;
if(!y) return x;
if(l == r){
tr[x].sum += tr[y].sum;
tr[x].ans = l;
return x;
}
mid;
ls[x] = Merge(ls[x],ls[y],l,m);
rs[x] = Merge(rs[x],rs[y],m+,r);
pushup(x);
return x;
} void dfs(ll u,ll fa){
for(ll i = head[u];i;i=e[i].next){
ll v = e[i].to;
if(v == fa) continue;
dfs(v,u);
Merge(root[u],root[v],,M);
}
update(a[u],,,M,root[u]);
ans[u] = tr[root[u]].ans;
} int main()
{
ll n,u,v;
scanf("%lld",&n);
for(ll i = ;i <= n;i ++){
scanf("%lld",&a[i]);
root[i] = i;
idx++;
}
for(ll i = ;i < n;i ++){
scanf("%lld%lld",&u,&v);
add(u,v); add(v,u);
}
dfs(,);
for(ll i = ;i <= n;i ++){
printf("%lld ",ans[i]);
}
return ; }

codeforces 600E . Lomsat gelral (线段树合并)的更多相关文章

  1. CF600E:Lomsat gelral(线段树合并)

    Description 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. Input 第一行一个$n$.第二行$n$个数字是$c[i]$.后面$n-1$ ...

  2. CodeForces600E Lomsat gelral 线段树合并

    从树上启发式合并搜出来的题 然而看着好像线段树合并就能解决??? 那么就用线段树合并解决吧 维护\(max, sum\)表示值域区间中的一个数出现次数的最大值以及所有众数的和即可 复杂度\(O(n \ ...

  3. CF600E Lomsat gelral——线段树合并/dsu on tree

    题目描述 一棵树有$n$个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. 这个题意是真的窒息...具体意思是说,每个节点有一个颜色,你要找的是每个子树中颜色的众数 ...

  4. Codeforces 600E - Lomsat gelral(树上启发式合并)

    600E - Lomsat gelral 题意 给出一颗以 1 为根的树,每个点有颜色,如果某个子树上某个颜色出现的次数最多,则认为它在这课子树有支配地位,一颗子树上,可能有多个有支配的地位的颜色,对 ...

  5. Codeforces 600E Lomsat gelral (树上启发式合并)

    题目链接 Lomsat gelral 占坑……等深入理解了再来补题解…… #include <bits/stdc++.h> using namespace std; #define rep ...

  6. codeforces 600E. Lomsat gelral 启发式合并

    题目链接 给一颗树, 每个节点有初始的颜色值. 1为根节点.定义一个节点的值为, 它的子树中出现最多的颜色的值, 如果有多种颜色出现的次数相同, 那么值为所有颜色的值的和. 每一个叶子节点是一个map ...

  7. Codeforces 600E. Lomsat gelral(Dsu on tree学习)

    题目链接:http://codeforces.com/problemset/problem/600/E n个点的有根树,以1为根,每个点有一种颜色.我们称一种颜色占领了一个子树当且仅当没有其他颜色在这 ...

  8. Codeforces 600E Lomsat gelral(dsu on tree)

    dsu on tree板子题.这个trick保证均摊O(nlogn)的复杂度,要求资瓷O(1)将一个元素插入集合,清空集合时每个元素O(1)删除.(当然log的话就变成log^2了) 具体的,每次先遍 ...

  9. codeforces 600E Lomsat gelral

    题面:codeforces600E 学习一下$dsu \ on \ tree$.. 这个东西可以处理很多无修改子树问题,复杂度通常为$O(nlogn)$. 主要操作是:我们先把整棵树链剖一下,然后每次 ...

随机推荐

  1. Python类与对象的理解

    注意python的类对象与实例对象的区分 类对象与实例对象是相对的,例如:a=1,那么a就是int的一个实例对象,这里的a相对于int来说,a是实例对象,int是类对象.但是int同时又是type的实 ...

  2. OSS网页上传和断点续传(OSS配置篇)

    OSS网页上传和断点续传主要根据BrowserJS-SDK和相关文档整理而得,快速构建OSS上传应用 一.Bucket设置 浏览器中直接访问OSS需要开通Bucket的CORS设置 将allowed ...

  3. Golang的类型断言

    类型断言即判断一个变量是不是某个类型的实例,这个经常用在判断接口的类型,基本的格式: y, ok := x.(type) 上面的语句用于判断变量x是不是type类型,有两种结果: x是type类型的变 ...

  4. Eclipse Todo Tasks 任务试图

    java - Find TODO tags in Eclipse - Stack Overflowhttps://stackoverflow.com/questions/16903046/find-t ...

  5. Jenkins deploy war to tomcat over https

    ssl - HTTPS login with Spring Security redirects to HTTP - Stack Overflow https://stackoverflow.com/ ...

  6. <c:forEach varStatus="status">中 varStatus的作用

    varStatus是<c:forEach>jstl循环标签的一个属性,varStatus属性. varStatus=“status”事实上定义了一个status名的对象作为varStatu ...

  7. [转帖]How To Be Successful

    How To Be Successful http://blog.samaltman.com/how-to-be-successful 总结一下文章的重点: 1. Compound yourself2 ...

  8. Oracle循环

    --无条件循环 declare v_num ; begin loop dbms_output.put_line(v_num); v_num:; ; end loop; end; --有条件循环 dec ...

  9. .Net中EF通用数据层小结

    增删改查: using System; using System.Collections.Generic; using System.Data; using System.Data.Entity; u ...

  10. 在JavaEE中使用Hibernate框架

    我们必须要了解一些Hibernate基础对象,如下: 配置对象 配置对象是你在任何 Hibernate 应用程序中创造的第一个 Hibernate 对象,并且经常只在应用程序初始化期间创造.它代表了 ...