题目链接

CF600E

题解

容易想到就是线段树合并,维护每个权值区间出现的最大值以及最大值位置之和即可

对于每个节点合并一下两个子节点的信息

要注意叶子节点信息的合并和非叶节点信息的合并是不一样的

由于合并不比逐个插入复杂度高,所以应是\(O(nlogn)\)的

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 100005,maxm = 8000005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
LL sum[maxm],ans[maxn];
int ls[maxm],rs[maxm],mx[maxm],cnt;
int n,c[maxn],fa[maxn],rt[maxn];
int h[maxn],ne = 1;
struct EDGE{int to,nxt;}ed[maxn << 1];
inline void build(int u,int v){
ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
}
inline void upd(int u){
sum[u] = 0;
if (mx[ls[u]] >= mx[rs[u]]){
mx[u] = mx[ls[u]];
sum[u] += sum[ls[u]];
}
if (mx[rs[u]] >= mx[ls[u]]){
mx[u] = mx[rs[u]];
sum[u] += sum[rs[u]];
}
}
void modify(int& u,int pre,int l,int r,int pos){
u = ++cnt; ls[u] = ls[pre]; rs[u] = rs[pre];
if (l == r){mx[u] = mx[pre] + 1; sum[u] = l; return;}
int mid = l + r >> 1;
if (mid >= pos) modify(ls[u],ls[pre],l,mid,pos);
else modify(rs[u],rs[pre],mid + 1,r,pos);
upd(u);
}
int merge(int u,int v,int l,int r){
if (!u) return v;
if (!v) return u;
int t = ++cnt,mid = l + r >> 1;
if (l == r){
mx[t] = mx[u] + mx[v];
sum[t] = l;
return t;
}
ls[t] = merge(ls[u],ls[v],l,mid);
rs[t] = merge(rs[u],rs[v],mid + 1,r);
upd(t);
return t;
}
void dfs(int u){
modify(rt[u],rt[u],1,n,c[u]);
Redge(u) if ((to = ed[k].to) != fa[u]){
fa[to] = u; dfs(to);
rt[u] = merge(rt[u],rt[to],1,n);
}
ans[u] = sum[rt[u]];
}
int main(){
n = read();
REP(i,n) c[i] = read();
for (int i = 1; i < n; i++) build(read(),read());
dfs(1);
REP(i,n) printf("%lld ",ans[i]);
return 0;
}

CF600E Lomsat gelral 【线段树合并】的更多相关文章

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

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

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

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

  3. 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 ...

  4. CodeForces600E Lomsat gelral 线段树合并

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

  5. CF600E Lomsat gelral 树上启发式合并

    题目描述 有一棵 \(n\) 个结点的以 \(1\) 号结点为根的有根树. 每个结点都有一个颜色,颜色是以编号表示的, \(i\) 号结点的颜色编号为 \(c_i\)​. 如果一种颜色在以 \(x\) ...

  6. CF600E Lomsat gelral (线段树合并)

    相当于是线段树合并的模板题,比(雨天的尾巴)还要板. 唯一注意的是线段树的更新,因为同一子树中可能有多种颜色占主导地位,要输出编号和,比如一颗子树中,1出现3次(最多),3出现3次,那么应该输出4. ...

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

    codeforces 600E E. Lomsat gelral 传送门:https://codeforces.com/contest/600/problem/E 题意: 给你一颗n个节点的树,树上的 ...

  8. BZOJ.3307.雨天的尾巴(dsu on tree/线段树合并)

    BZOJ 洛谷 \(dsu\ on\ tree\).(线段树合并的做法也挺显然不写了) 如果没写过\(dsu\)可以看这里. 对修改操作做一下差分放到对应点上,就成了求每个点子树内出现次数最多的颜色, ...

  9. [XJOI NOI2015模拟题13] C 白黑树 【线段树合并】

    题目链接:XJOI - NOI2015-13 - C 题目分析 使用神奇的线段树合并在 O(nlogn) 的时间复杂度内解决这道题目. 对树上的每个点都建立一棵线段树,key是时间(即第几次操作),动 ...

随机推荐

  1. 传输控制协议--- Transmission Control Protocol (TCP)

    Transmission Control Protocol (TCP) 用于网络通信的传输控制和网络协议套件,包括很多协议,其中最主要的是TCP和IP协议.TCP/IP属于UNIX类系统的内置协议,被 ...

  2. 2.2 Oracle之DML的SQL语句之多表查询以及组函数

    一.SQL的多表查询: 1.左连接和右连接(不重要一方加(+)) SELECT e.empno,e.ename,d.deptno,d.dname,d.loc FROM emp e,dept d WHE ...

  3. BAT面试必备——Java 集合类

    本文首发于我的个人博客:尾尾部落 1. Iterator接口 Iterator接口,这是一个用于遍历集合中元素的接口,主要包含hashNext(),next(),remove()三种方法.它的一个子接 ...

  4. linux 启动自动运行

    开机启动时自动运行程序  Linux    1.加载后, 它将初始化硬件和设备驱动, 然后运行第一个进程init.init根据配置文件继续引导过程,启动其它进程.通常情况下,修改放置在 /etc/rc ...

  5. 【坚持】Selenium+Python学习之从读懂代码开始 DAY4

    2018/05/21 [生成器详解:廖雪峰的官方网站](https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d ...

  6. jsp内置对象 转发与重定向的区别

    jsp 内置对象  转发与重定向的比较 重定向和转发有一个重要的不同:当使用转发时,JSP容器将使用一个内部的方法来调用目标页面,新的页面继续处理同一个请求,而浏览器将不会知道这个过程. 与之相反,重 ...

  7. WebRtc与SIP

    最近研究一下 webrtc ,看了几篇paper,之前也尝试运行验证了几个demo,现在把我的理解总结到这里. WebRTC 简介 WebRTC,名称源自网页实时通信(Web Real-Time Co ...

  8. 如何掌握 Kubernetes ?系统学习 k8s 的大纲一份

    深度剖析 Kubernetes 深度剖析 k8s 如何学习 Kubernetes ?如何入门 Kubernetes? 为了帮帮初学者,2018 年 InfoQ 旗下(就是你知道的那个 InfoQ 哇) ...

  9. 为什么HashMap桶(链表)的长度超过8会转换成红黑树?

    百度了一下,感觉能说清楚的并不多,所以在此记录一下. 首先说一说转换为红黑树的必要性: 红黑树的插入.删除和遍历的最坏时间复杂度都是log(n), 因此,意外的情况或者恶意使用下导致hashCode( ...

  10. du命令详解

    基础命令学习目录首页 原文链接:https://blog.csdn.net/linuxnews/article/details/51207738 导读du命令是检查硬盘使用情况,统计文件或目录及子目录 ...