CF600E Lomsat gelral (线段树合并)

相当于是线段树合并的模板题,比(雨天的尾巴)还要板。

唯一注意的是线段树的更新,因为同一子树中可能有多种颜色占主导地位,要输出编号和,比如一颗子树中,1出现3次(最多),3出现3次,那么应该输出4。

复制代码
 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N = 1e5 + 10, M = 1e5;
 5 struct node {
 6     int lc, rc;
 7     ll dat, num;//dat次数最多颜色的次数,num编号和 
 8 }tr[N * 50];
 9 int head[N], to[N << 1], nxt[N << 1], tot;
10 int n, rt[N], cnt, co[N];
11 ll ans[N];
12 void add(int x, int y) {
13     nxt[++tot] = head[x];
14     head[x] = tot;
15     to[tot] = y;
16 }
17 
18 void pushup(int k) {//注意
19     node a = tr[tr[k].lc], b = tr[tr[k].rc];
20     if (a.dat > b.dat) {
21         tr[k].dat = a.dat;
22         tr[k].num = a.num;
23     }
24     else if (a.dat < b.dat) {
25         tr[k].dat = b.dat;
26         tr[k].num = b.num;
27     }
28     else {
29         tr[k].dat = a.dat;
30         tr[k].num = a.num + b.num;
31     }
32 }
33 
34 void insert(int p, int l, int r, int pos, int val) {
35     if (l == r) {
36         tr[p].dat += val;
37         tr[p].num = l;
38         return ;
39     }
40     int mid = (l + r) >> 1;
41     if (pos <= mid) {
42         if (!tr[p].lc) tr[p].lc = ++cnt;
43         insert(tr[p].lc, l, mid, pos, val);
44     }
45     else {
46         if (!tr[p].rc) tr[p].rc = ++cnt;
47         insert(tr[p].rc, mid + 1, r, pos, val);
48     }
49     pushup(p);
50 } 
51 
52 int merge(int p, int q, int l, int r) {
53     if (!p || !q) return p + q;
54     if (l == r) {
55         tr[p].dat += tr[q].dat;
56         tr[p].num = l;
57         return p;
58     }
59     int mid = (l + r) >> 1;
60     tr[p].lc = merge(tr[p].lc, tr[q].lc, l, mid);
61     tr[p].rc = merge(tr[p].rc, tr[q].rc, mid + 1, r);
62     pushup(p);
63     return p;
64 }
65 
66 void dfs(int u, int f) {
67     for (int i = head[u]; i; i = nxt[i]) {
68         int v = to[i];
69         if (v == f) continue;
70         dfs(v, u);
71         rt[u] = merge(rt[u], rt[v], 1, M);
72     }
73     ans[u] = tr[rt[u]].num;
74 }
75 
76 int main() {
77     scanf("%d", &n);
78     for (int i = 1; i <= n; i++) {
79         scanf("%d", &co[i]);
80         rt[i] = ++cnt;
81         insert(rt[i], 1, M, co[i], 1);
82     }
83     for (int i = 1; i < n; i++) {
84         int a, b;
85         scanf("%d%d", &a, &b);
86         add(a, b),add(b, a);
87     }
88     dfs(1, 0);
89     for (int i = 1; i <= n; i++) printf("%lld ", ans[i]);
90     return 0;
91 }
92 /*
93 4
94 1 2 3 4
95 1 2
96 2 3
97 2 4
98 */
复制代码

 



如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   YHXo  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示