codeforces 600E E. Lomsat gelral

传送门:https://codeforces.com/contest/600/problem/E

题意:

给你一颗n个节点的树,树上的每一个节点都有一种颜色,询问每一个节点所在的子树颜色数量最多的那些颜色的值的总和

题解:

维护子树颜色的数量和答案,线段树合并即可

代码:

/**
*        ┏┓    ┏┓
*        ┏┛┗━━━━━━━┛┗━━━┓
*        ┃       ┃  
*        ┃   ━    ┃
*        ┃ >   < ┃
*        ┃       ┃
*        ┃... ⌒ ...  ┃
*        ┃       ┃
*        ┗━┓   ┏━┛
*          ┃   ┃ Code is far away from bug with the animal protecting          
*          ┃   ┃ 神兽保佑,代码无bug
*          ┃   ┃           
*          ┃   ┃       
*          ┃   ┃
*          ┃   ┃           
*          ┃   ┗━━━┓
*          ┃       ┣┓
*          ┃       ┏┛
*          ┗┓┓┏━┳┓┏┛
*           ┃┫┫ ┃┫┫
*           ┗┻┛ ┗┻┛
*/
// warm heart, wagging tail,and a smile just for you!
//
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// .' \| |// `.
// / \||| : |||// \
// / _||||| -:- |||||- \
// | | \ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// 佛祖保佑 永无BUG
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <bitset>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
double ans = 1.0;
while(b) {
if(b % 2)ans = ans * a;
a = a * a;
b /= 2;
} return ans;
}
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
struct node {
int l, r, sum, val;
LL ans;
} tree[maxn * 50];
int root[maxn];
int col[maxn];
int tree_cnt;
struct EDGE {
int v, nxt;
} edge[maxn << 1];
int head[maxn], tot; void add_edge(int u, int v) {
edge[tot].v = v;
edge[tot].nxt = head[u];
head[u] = tot++;
}
#define ls tree[rt].l
#define rs tree[rt].r
void push_up(int rt) {
if(tree[ls].sum == tree[rs].sum) {
tree[rt].sum = tree[ls].sum;
tree[rt].val = tree[ls].sum;
tree[rt].ans = tree[ls].ans + tree[rs].ans;
} else if(tree[ls].sum > tree[rs].sum) {
tree[rt].sum = tree[ls].sum;
tree[rt].val = tree[ls].val;
tree[rt].ans = tree[ls].ans;
} else {
tree[rt].sum = tree[rs].sum;
tree[rt].val = tree[rs].val;
tree[rt].ans = tree[rs].ans;
}
}
void update(int &x, int l, int r, int pos, int val) {
if(!x) x = ++tree_cnt;
if(l == r) {
tree[x].val = l;
tree[x].sum += val;
tree[x].ans = l;
return;
}
int mid = (l + r) >> 1;
if(pos <= mid) update(tree[x].l, l, mid, pos, val);
else update(tree[x].r, mid + 1, r, pos, val);
push_up(x);
}
int merge(int x, int y, int l, int r) {
if(!x) return y;
if(!y) return x;
if(l == r) {
tree[x].val = l;
tree[x].sum += tree[y].sum;
tree[x].ans = l;
return x;
}
int mid = (l + r) >> 1;
tree[x].l = merge(tree[x].l, tree[y].l, l, mid);
tree[x].r = merge(tree[x].r, tree[y].r, mid + 1, r);
push_up(x);
return x;
}
int Max = 100000;
LL ans[maxn];
void dfs(int u, int fa) {
for(int i = head[u]; i != -1; i = edge[i].nxt) {
int v = edge[i].v;
if(v == fa) continue;
dfs(v, u);
merge(root[u], root[v], 1, Max);
}
update(root[u], 1, Max, col[u], 1);
ans[u] = tree[root[u]].ans;
}
void init() {
memset(head, -1, sizeof(head));
memset(col, 0, sizeof(col));
tree_cnt = tot = 0; }
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int n;
scanf("%d", &n);
init();
for(int i = 1; i <= n; i++) {
scanf("%d", &col[i]);
root[i] = i;
tree_cnt++;
}
for(int i = 1, u, v; i < n; i++) {
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
dfs(1, 0);
for(int i = 1; i <= n; i++) {
printf("%lld%c", ans[i], i == n ? '\n' : ' ');
}
return 0;
}

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

  1. codeforces 600E . Lomsat gelral (线段树合并)

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

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

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

  3. CodeForces600E Lomsat gelral 线段树合并

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

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

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

  5. Codeforces ECR47F Dominant Indices(线段树合并)

    一个比较显然的做法:对每棵子树用线段树维护其中的深度,线段树合并即可. 本来想用这个题学一下dsu on tree,结果还是弃疗了. #include<iostream> #include ...

  6. CodeForces - 1037H: Security(SAM+线段树合并)

    题意:给定字符串S:  Q次询问,每次询问给出(L,R,T),让你在S[L,R]里面找一个字典序最小的子串,其字典序比T大. 没有则输出-1: 思路:比T字典序大,而且要求字典最小,显然就是在T的尾巴 ...

  7. DSU On Tree——Codeforces 600E(E. Lomsat gelral)

    有这么一类问题,要求统计一棵树上与子树相关的某些信息,比如:在一棵所有节点被染色的树上,统计每棵子树上出现次数最多的颜色编号之和. 很自然的可以想到用DFS序+主席树去求解,但是编码复杂度很高: 然后 ...

  8. Codeforces 600 E. Lomsat gelral (dfs启发式合并map)

    题目链接:http://codeforces.com/contest/600/problem/E 给你一棵树,告诉你每个节点的颜色,问你以每个节点为根的子树中出现颜色次数最多的颜色编号和是多少. 最容 ...

  9. CF600E Lomsat gelral 【线段树合并】

    题目链接 CF600E 题解 容易想到就是线段树合并,维护每个权值区间出现的最大值以及最大值位置之和即可 对于每个节点合并一下两个子节点的信息 要注意叶子节点信息的合并和非叶节点信息的合并是不一样的 ...

随机推荐

  1. (五)IO流之ByteArrayInput/OutputStream

    ByteArrayInputStream:是把字节数组当成源的输入流 String string="hello shanghai"; ByteArrayInputStream bi ...

  2. python HTTP请求过程

  3. python 异常层级

  4. 基于颜色的R2V软件快速矢量化

    跟同学一起做SRTP,矢量化,作图的工作点名让我去做,人家说,谁让你是学地理信息的呢?哎,什么时候地理信息不再被别人当成制图画图的,我们专业就有希望了. 话虽然这么说,但工作还是要去做. (进入正题) ...

  5. ArcGIS下如何提取研究区域

    举个例子,如果我用“按位置选择工具”从shitrt图层中提取普查小区在count6中的部分,并将结果输出为shapefile文件cnty6trt,可以这么做: 就OK了

  6. HLSL像素着色器

    原文:HLSL像素着色器 昨日不可追, 今日尤可为.勤奋,炽诚,不忘初心 手机淘宝二维码 扫描       或者打开连接:程序设计开发 ,掌声鼓励,欢迎光临.     像素着色器替代了固定渲染管线的  ...

  7. Flask学习之十三 日期和时间

    英文博客地址:http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xiii-dates-and-times 中文翻译地址: ...

  8. 自定义View系列教程08--滑动冲突的产生及其处理

    深入探讨Android异步精髓Handler 站在源码的肩膀上全解Scroller工作机制 Android多分辨率适配框架(1)- 核心基础 Android多分辨率适配框架(2)- 原理剖析 Andr ...

  9. 最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)

    最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字 ...

  10. Android读取sd卡

    public static String[] getStoragePaths() { List<String> pathsList = new ArrayList<String> ...