樹上啟發式合併(dsu on tree)
但這個 dsu 應該和並查集沒啥關係
總體思想就是利用重鏈剖分的性質,將小堆(輕兒子)往大堆(重兒子)合併,這樣子可以達到 log 的複雜度
以下是幾個重要函式
void dfs1(int u, int father){}
得到一系列重要陣列,其中包括son[]
void dfs2(int u, int op){}
計算 u 子樹的答案add_ans(int u, int xson){}
將 u 子樹除了 xson 子樹的所有加入答案,是合併輕子樹的操作del_ans(int u){}
將 u 子樹的答案刪除,清空 cnt 陣列,用於第一遍 dfs2 後輕子樹的刪除操作
第一次敲的時候 add_ans 函式敲成了 add 函式......
int n, m;
ll col[N];
int head[N], cnt;
struct Edge{
int from, to, nxt;
}e[N << 1];
void add(int u, int v){
e[++cnt].from = u;
e[cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
int deep[N], fa[N], siz[N], son[N];
void dfs1(int u, int father){
fa[u] = father;
deep[u] = deep[father] + 1;
siz[u] = 1;
for(int i = head[u]; i != 0; i = e[i].nxt){
int v = e[i].to;
if(v == father) continue;
dfs1(v, u);
siz[u] += siz[v];
if(!son[u] || siz[son[u]] < siz[v]) son[u] = v;
}
}
ll tmpans, ans_cnt, num[N], ans[N];
void add_ans(int u, int xson){
num[col[u]]++;
if(num[col[u]] == ans_cnt){
tmpans += col[u];
}else if(num[col[u]] > ans_cnt){
ans_cnt = num[col[u]];
tmpans = col[u];
}
for(int i = head[u]; i != 0; i = e[i].nxt){
int v = e[i].to;
if(v == xson || v == fa[u]) continue;
add_ans(v, xson);
}
}
void del_ans(int u){
num[col[u]]--;
for(int i = head[u]; i != 0; i = e[i].nxt){
int v = e[i].to;
if(v == fa[u]) continue;
del_ans(v);
}
}
void dfs2(int u, int op){
for(int i = head[u]; i != 0; i = e[i].nxt){
int v = e[i].to;
if(v == fa[u] || v == son[u]) continue;
dfs2(v, 0);
}
if(son[u] != 0){
dfs2(son[u], 1);
}
add_ans(u, son[u]);
ans[u] = tmpans;
if(op == 0){
tmpans = ans_cnt = 0;
del_ans(u);
}
}
Lomsat gelral
題面翻譯
- 有一棵 \(n\) 個結點的以 \(1\) 號結點為根的有根樹。
- 每個結點都有一個顏色,顏色是以編號表示的, \(i\) 號結點的顏色編號為 \(c_i\)。
- 如果一種顏色在以 \(x\) 為根的子樹內出現次數最多,稱其在以 \(x\) 為根的子樹中佔主導地位。顯然,同一子樹中可能有多種顏色占主導地位。
- 你的任務是對於每一個 \(i\in[1,n]\),求出以 \(i\) 為根的子樹中,占主導地位的顏色的編號和。
- \(n\le 10^5,c_i\le n\)
題目描述
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 $ .
輸入格式
The first line contains integer $ n $ ( $ 1<=n<=10^{5} $ ) — the number of vertices in the tree.
The second line contains $ n $ integers $ c_{i} $ ( $ 1<=c_{i}<=n $ ), $ c_{i} $ — the colour of the $ i $ -th vertex.
Each of the next $ n-1 $ lines contains two integers $ x_{j},y_{j} $ ( $ 1<=x_{j},y_{j}<=n $ ) — the edge of the tree. The first vertex is the root of the tree.
輸出格式
Print $ n $ integers — the sums of dominating colours for each vertex.
樣例 #1
樣例輸入 #1
4
1 2 3 4
1 2
2 3
2 4
樣例輸出 #1
10 9 3 4
樣例 #2
樣例輸入 #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