CF EDU - E. Lomsat gelral 树上启发式合并
学习:http://codeforces.com/blog/entry/44351
题意:
给定一个以1为根节点的树,每个节点都有一个颜色,问每个节点的子树中,颜色最多的是哪几种颜色,输出这些颜色的值得和。
思路:
树上启发式合并的模板题,具体来说,先对树进行树链剖分,分出一个重链和轻边,dfs时,把每条轻儿子暴力加到根节点中,每次加的时候,用这样的技巧
if(csz < cnt[col[v]]) sum = col[v] , csz = cnt[col[v]];
else if(csz==cnt[col[v]]) sum += col[v];
就可以使得sum中保存的是这个节点的子树中数量相同且最多的颜色和。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <list>
#include <cstdlib>
#include <iterator>
#include <cmath>
#include <iomanip>
#include <bitset>
#include <cctype>
using namespace std;
//#pragma comment(linker, "/STACK:102400000,102400000") //c++
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue typedef long long ll;
typedef unsigned long long ull; typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii; //priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
#define endl '\n' #define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A) //用来压行
#define REP(i , j , k) for(int i = j ; i < k ; ++i)
//priority_queue<int ,vector<int>, greater<int> >que; const ll mos = 0x7FFFFFFF; //
const ll nmos = 0x80000000; //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; // template<typename T>
inline T read(T&x){
x=;int f=;char ch=getchar();
while (ch<''||ch>'') f|=(ch=='-'),ch=getchar();
while (ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
return x=f?-x:x;
}
// #define _DEBUG; //*//
#ifdef _DEBUG
freopen("input", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
/*-----------------show time----------------*/
const int maxn = 1e5+;
vector<int>g[maxn];
vector<int>v[maxn];
int cnt[maxn],col[maxn];
ll ans[maxn];
bool big[maxn];
int n;
int sz[maxn]; void dfs1(int v,int fa){
sz[v] = ;
for(int i=; i<g[v].size(); i++){
int u = g[v][i];
if(u!=fa){
dfs1(u,v);
sz[v]+=sz[u];
}
}
}
ll sum = ,csz = ;
// priority_queue<int>que;
void add(int v, int fa,int x){ cnt[col[v]] += x;
// if(v==1)cout<<"$$"<<cnt[col[v]]<<endl;
if(csz < cnt[col[v]]) sum = col[v] , csz = cnt[col[v]];
else if(csz==cnt[col[v]]) sum += col[v]; for(int i=;i<g[v].size(); i++){
int u = g[v][i];
if(u!=fa && big[u]==){
add(u,v,x);
}
}
} void dfs(int v,int fa,int keep){
int mx = -,bigChild = -; for(int i=; i<g[v].size(); i++){
int u = g[v][i];
if(u!=fa && sz[u] > mx)
mx = sz[u], bigChild = u;
} for(int i=; i<g[v].size(); i++){
int u = g[v][i];
if(u!=fa && u!=bigChild){
dfs(u,v,);////////////
}
} if(bigChild!=-){
dfs(bigChild,v,),big[bigChild] = ;/////////
} add(v,fa,); ////////
ans[v] = sum;
/*
debug(v);
for(int i=1; i<=n; i++){
cout<<cnt[i]<<" ";
}
cout<<endl;
*/
if(bigChild!=-) big[bigChild] = ;
if(keep==){
add(v,fa,-);
sum = ;csz = ;
}
/*
debug(v);
for(int i=1; i<=n; i++){
cout<<cnt[i]<<" ";
}
cout<<endl;
*/
} int main(){
scanf("%d", &n);
for(int i=; i<=n; i++)scanf("%d", &col[i]);
for(int i=; i<n; i++){
int u,v;
scanf("%d%d", &u, &v);
g[u].pb(v);
g[v].pb(u);
}
dfs1(,);
dfs(,,);
for(int i=; i<=n; i++)printf("%lld " , ans[i]);
printf("\n");
return ;
}
EDU#2E
CF EDU - E. Lomsat gelral 树上启发式合并的更多相关文章
- CF 600 E Lomsat gelral —— 树上启发式合并
题目:http://codeforces.com/contest/600/problem/E 看博客:https://blog.csdn.net/blue_kid/article/details/82 ...
- 【CF600E】Lomsat gelral——树上启发式合并
(题面来自luogu) 题意翻译 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. ci <= n <= 1e5 裸题.统计时先扫一遍得到出 ...
- CF600E Lomsat gelral 树上启发式合并
题目描述 有一棵 \(n\) 个结点的以 \(1\) 号结点为根的有根树. 每个结点都有一个颜色,颜色是以编号表示的, \(i\) 号结点的颜色编号为 \(c_i\). 如果一种颜色在以 \(x\) ...
- Codeforces 600 E. Lomsat gelral (dfs启发式合并map)
题目链接:http://codeforces.com/contest/600/problem/E 给你一棵树,告诉你每个节点的颜色,问你以每个节点为根的子树中出现颜色次数最多的颜色编号和是多少. 最容 ...
- Codeforces 600E - Lomsat gelral(树上启发式合并)
600E - Lomsat gelral 题意 给出一颗以 1 为根的树,每个点有颜色,如果某个子树上某个颜色出现的次数最多,则认为它在这课子树有支配地位,一颗子树上,可能有多个有支配的地位的颜色,对 ...
- [Codeforces600E] Lomsat gelral(树上启发式合并)
[Codeforces600E] Lomsat gelral(树上启发式合并) 题面 给出一棵N个点的树,求其所有子树内出现次数最多的颜色编号和.如果多种颜色出现次数相同,那么编号都要算进答案 N≤1 ...
- 【学习笔记/题解】树上启发式合并/CF600E Lomsat gelral
题目戳我 \(\text{Solution:}\) 树上启发式合并,是对普通暴力的一种优化. 考虑本题,最暴力的做法显然是暴力统计每一次的子树,为了避免其他子树影响,每次统计完子树都需要清空其信息. ...
- 【CF600E】Lomset gelral 题解(树上启发式合并)
题目链接 题目大意:给出一颗含有$n$个结点的树,每个节点有一个颜色.求树中每个子树最多的颜色的编号和. ------------------------- 树上启发式合并(dsu on tree). ...
- 树上启发式合并(dsu on tree)学习笔记
有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...
随机推荐
- jquery的addClass、removeClass、toggleClass方法
1.addClass()添加类 1.1 用jquery为某一个元素添加类 $("div").addClass("active");//给div元素添加activ ...
- 模块购物商城和ATM机代码:
http://outofmemory.cn/python/video/let-us-python/ python为程序员服务 快来加入群[python爬虫交流群](群号570070796),发现精彩 ...
- CentOS 7.3下使用YUM 安装MySQL5.6
1.检查Linux系统中是否已安装 MySQL rpm -qa | grep mysql 返回空值的话,就说明没有安装 MySQL 注意:在新版本的CentOS7中,默认的数据库已更新为了Mariad ...
- 拉格朗日对偶性(Lagrange duality)
目录 拉格朗日对偶性(Lagrange duality) 1. 从原始问题到对偶问题 2. 弱对偶与强对偶 3. KKT条件 Reference: 拉格朗日对偶性(Lagrange duality) ...
- 二叉查找树(查找、插入、删除)——C语言
二叉查找树 二叉查找树(BST:Binary Search Tree)是一种特殊的二叉树,它改善了二叉树节点查找的效率.二叉查找树有以下性质: (1)若左子树不空,则左子树上所有节点的值均小于它的根节 ...
- .NETCoreCSharp 中级篇2-3 Linq简介
.NETCoreCSharp 中级篇2-3 本节内容为Linq及其拓展方法.Linq中表达式树的使用 简介 语言集成查询(LINQ)是一系列直接将查询功能集成到C#语言的技术统称.数据查询历来都表示为 ...
- 理解Go协程与并发
协程 Go语言里创建一个协程很简单,使用go关键字就可以让一个普通方法协程化: package main import ( "fmt" "time" ) fun ...
- 第 10 篇:小细节 Markdown 文章自动生成目录,提升阅读体验
目录 在文中插入目录 在页面的任何地方插入目录 处理空目录 美化标题的锚点 URL 作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 上 ...
- 重读《学习JavaScript数据结构与算法-第三版》- 第6章 链表(一)
定场诗 伤情最是晚凉天,憔悴厮人不堪言: 邀酒摧肠三杯醉.寻香惊梦五更寒. 钗头凤斜卿有泪,荼蘼花了我无缘: 小楼寂寞新雨月.也难如钩也难圆. 前言 本章为重读<学习JavaScript数据结构 ...
- Python循环语句及函数的定义
循环语句¶ 重复执行某一个固定的动作或者任务 语法 for 变量 in序列: 语句1 语句2 ..... In [2]: # 列表知识只是以后会讲 # 比如[1,2,3,4,5,6,7] list ...