题目
题目描述
You are given a rooted tree with root in vertex 11 . Each vertex is coloured in some colour.
Let’s call colour cc dominating in the subtree of vertex vv if there are no other colours that appear in the subtree of vertex vv more times than colour cc . So it’s possible that two or more colours will be dominating in the subtree of some vertex.
The subtree of vertex vv is the vertex vv and all other vertices that contains vertex vv in each path to the root.
For each vertex vv find the sum of all dominating colours in the subtree of vertex vv .
输入格式
The first line contains integer nn ( 1<=n<=10^{5}1<=n<=10
5
) — the number of vertices in the tree.
The second line contains nn integers c_{i}c
i
( 1<=c_{i}<=n1<=c
i
<=n ), c_{i}c
i
— the colour of the ii -th vertex.
Each of the next n-1n−1 lines contains two integers x_{j},y_{j}x
j
,y
j
( 1<=x_{j},y_{j}<=n1<=x
j
,y
j
<=n ) — the edge of the tree. The first vertex is the root of the tree.
输出格式
Print nn integers — the sums of dominating colours for each vertex.
题意翻译
有一棵 nn 个结点的以 11 号结点为根的有根树。
每个结点都有一个颜色,颜色是以编号表示的, ii 号结点的颜色编号为 c_ic
i
。
如果一种颜色在以 xx 为根的子树内出现次数最多,称其在以 xx 为根的子树中占主导地位。显然,同一子树中可能有多种颜色占主导地位。
你的任务是对于每一个 i\in[1,n]i∈[1,n],求出以 ii 为根的子树中,占主导地位的颜色的编号和。
n\le 10^5,c_i\le nn≤10
5
,c
i
≤n
输入输出样例
输入 #1复制
4
1 2 3 4
1 2
2 3
2 4
输出 #1复制
10 9 3 4
输入 #2复制
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
输出 #2复制
6 5 4 3 2 3 3 1 1 3 2 2 1 2 3
思路
显然dsu on tree板子题,但今天我是来学线段树合并的
对于每一个点开一棵动态开点权值线段树,然后维护最大值。
转移时线段树合并即可
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct Seg
{
int l,r,sum,val,ans;
}tr[5000077];
const int N=1e5+77;
int rt[N],cl[N],cnt,n,anss[N];
vector<int> g[N];
int push_up(int u)
{
if(tr[tr[u].l].sum>tr[tr[u].r].sum)
{
tr[u].sum=tr[tr[u].l].sum;
tr[u].val=tr[tr[u].l].val;
tr[u].ans=tr[tr[u].l].ans;
}
if(tr[tr[u].r].sum>tr[tr[u].l].sum)
{
tr[u].sum=tr[tr[u].r].sum;
tr[u].val=tr[tr[u].r].val;
tr[u].ans=tr[tr[u].r].ans;
}
if(tr[tr[u].l].sum==tr[tr[u].r].sum)
{
tr[u].sum=tr[tr[u].l].sum;
tr[u].val=tr[tr[u].l].val;
tr[u].ans=tr[tr[u].l].ans+tr[tr[u].r].ans;
}
}
int update(int &u,int l,int r,int pos,int v)
{
if(!u) u=++cnt;
if(l==r)
{
tr[u].val=l;
tr[u].sum+=v;
tr[u].ans=l;
return 0;
}
int mid=(l+r)>>1;
if(pos<=mid) update(tr[u].l,l,mid,pos,v);
else update(tr[u].r,mid+1,r,pos,v);
push_up(u);
}
int merge(int a,int b,int l,int r)
{
if(!a) return b;
if(!b) return a;
if(l==r)
{
tr[a].val=l;
tr[a].sum+=tr[b].sum;
tr[a].ans=l;
return a;
}
int mid=(l+r)>>1;
tr[a].l=merge(tr[a].l,tr[b].l,l,mid);
tr[a].r=merge(tr[a].r,tr[b].r,mid+1,r);
push_up(a);
return a;
}
int dfs(int u,int f)
{
for(int i=0; i<g[u].size(); i++)
{
if(g[u][i]==f) continue;
dfs(g[u][i],u);
merge(rt[u],rt[g[u][i]],1,100000);
}
update(rt[u],1,100000,cl[u],1);
anss[u]=tr[rt[u]].ans;
}
signed main()
{
scanf("%lld",&n);
for(int i=1; i<=n; i++)
{
scanf("%lld",&cl[i]);
rt[i]=i;
cnt++;
}
int from,to;
for(int i=1; i<n; i++)
{
scanf("%lld%lld",&from,&to);
g[from].push_back(to);
g[to].push_back(from);
}
dfs(1,0);
for(int i=1; i<=n; i++)
{
printf("%lld ",anss[i]);
}
}