codeforces600E Lomsat gelral
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:codeforces600E
解法一:$O(nlog^2n)$
正解:启发式合并
解题报告:
这道题求的是每个点的子树内的出现次数最大的数字的和。
考虑启发式合并,我用$col[x]$的$map$表示$x$的子树内的每种权值的出现次数,$sum[x]$的$map$表示$x$的子树内每种出现次数的权值和。
那么我在将儿子节点和父亲节点合并的时候只需要根据$col$的$size$,把小的往大的里面暴力合并就可以了。
$get$了$map$的正确姿势…
//It is made by ljh2000
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <complex>
#include <bitset>
using namespace std;
typedef long long LL;
typedef long double LB;
const double pi = acos(-1);
const int MAXN = 100011;
const int MAXM = 200011;
int n,a[MAXN],ecnt,first[MAXN],to[MAXM],next[MAXM];
LL ans[MAXN];
map<int,int>col[MAXN];//统计每种颜色的出现次数
map<int,LL>sum[MAXN];//统计每种出现次数的sum
inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; }
inline int getint(){
int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
} inline void dfs(int x,int fa){
col[x][a[x]]=1;
sum[x][1]=a[x];
int now,cc;
for(int i=first[x];i;i=next[i]) {
int v=to[i]; if(v==fa) continue;
dfs(v,x);
if(col[x].size()<col[v].size()) swap(col[x],col[v]),swap(sum[x],sum[v]);//小的往大的上面合并!!!
for(map<int,int>::iterator it=col[v].begin();it!=col[v].end();it++) {
now=it->first; cc=it->second;
if(col[x].count(now)>0) {
sum[x][col[x][now]]-=now;
col[x][now]+=cc;
sum[x][col[x][now]]+=now;
}
else col[x][now]=col[v][now],sum[x][col[x][now]]+=now;
}
}
map<int,LL>::iterator it=sum[x].end();
it--;//最大的应该是end-1,end是一个空指针...
ans[x]=it->second;
} inline void work(){
n=getint(); for(int i=1;i<=n;i++) a[i]=getint(); int x,y;
for(int i=1;i<n;i++) { x=getint(); y=getint(); link(x,y); link(y,x); }
dfs(1,0);
for(int i=1;i<=n;i++)
printf("%I64d ",ans[i]);
} int main()
{
work();
return 0;
}
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
解法二:$O(nlogn)$
正解:$dsu$ $on$ $tree$
解题报告:
学了一发$dsu$ $on$ $tree$。
这个算法主要处理的是对于树上某一特征的不带修改子树统计问题,通常可以做到$O(nlogn)$。
大概做法就是先链剖,然后我考虑用一个全局数组$cnt$来表示某个值的出现次数,如果是暴力的做法的话,就是每次处理一个节点时暴力把整棵子树的贡献加入,同时更新答案,做完之后暴力把整棵子树的贡献消除,递归做儿子节点。
而$dsu$ $on$ $tree$的做法就是,每次先递归处理完轻儿子,然后再做重儿子。
到了统计答案的时候,同样是把贡献暴力加入,但是假如这个点是他的父亲节点的重儿子,那么不消除贡献(所以加入贡献的时候注意不要加到重儿子上去了),往上走,直到某个点是父亲的轻儿子再把整棵子树的贡献消除即可。
//It is made by ljh2000
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <complex>
#include <bitset>
using namespace std;
typedef long long LL;
typedef long double LB;
typedef complex<double> C;
const double pi = acos(-1);
const int MAXN = 100011;
const int MAXM = 200011;
int n,a[MAXN],cnt[MAXN],ecnt,first[MAXN],to[MAXM],next[MAXM],size[MAXN],son[MAXN],Son;
LL sum,Max,ans[MAXN];
inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; }
inline int getint(){
int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
} inline void dfs(int x,int fa){
size[x]=1;
for(int i=first[x];i;i=next[i]) {
int v=to[i]; if(v==fa) continue;
dfs(v,x); size[x]+=size[v];
if(size[v]>size[son[x]]) son[x]=v;
}
} inline void add(int x,int fa,int val){
cnt[ a[x] ]+=val;
if(cnt[ a[x] ]>Max) Max=cnt[ a[x] ],sum=a[x];
else if(cnt[ a[x] ]==Max) sum+=a[x];
for(int i=first[x];i;i=next[i]) {
int v=to[i]; if(v==fa || v==Son) continue;
add(v,x,val);
}
} inline void solve(int x,int fa,bool T){
for(int i=first[x];i;i=next[i]) {
int v=to[i]; if(v==fa || v==son[x]) continue;
solve(v,x,1);
} if(son[x])
solve(son[x],x,0),Son=son[x]; add(x,fa,1); Son=0;
ans[x]=sum; if(T==1)
add(x,fa,-1),sum=Max=0;
} inline void work(){
n=getint(); for(int i=1;i<=n;i++) a[i]=getint();
int x,y; for(int i=1;i<n;i++) { x=getint(); y=getint(); link(x,y); link(y,x); }
dfs(1,0);
solve(1,0,1);
for(int i=1;i<=n;i++)
printf("%I64d ",ans[i]);
} int main()
{
work();
return 0;
}
//有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
codeforces600E Lomsat gelral的更多相关文章
- [Codeforces600E] Lomsat gelral(树上启发式合并)
[Codeforces600E] Lomsat gelral(树上启发式合并) 题面 给出一棵N个点的树,求其所有子树内出现次数最多的颜色编号和.如果多种颜色出现次数相同,那么编号都要算进答案 N≤1 ...
- CodeForces600E Lomsat gelral 线段树合并
从树上启发式合并搜出来的题 然而看着好像线段树合并就能解决??? 那么就用线段树合并解决吧 维护\(max, sum\)表示值域区间中的一个数出现次数的最大值以及所有众数的和即可 复杂度\(O(n \ ...
- codeforces600E. Lomsat gelral(dsu on tree)
dsu on tree先分轻重儿子先处理轻边,再处理重儿子再加上轻儿子的答案 #include<iostream> #include<cstdio> #include<q ...
- codeforces600E Lomsat gelral【线段树合并/DSU】
第一次AC这道题,是三年前的一个下午,也许晚上也说不定.当时使用的\(DSU\) \(on\) \(tree\)算法,如今已经淡忘,再学习新的算法过程中,却与旧物重逢.生活中充满不可知会的相遇,即使重 ...
- Educational Codeforces Round 2 E. Lomsat gelral 启发式合并map
E. Lomsat gelral Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/600/prob ...
- Codeforces 600 E - Lomsat gelral
E - Lomsat gelral 思路1: 树上启发式合并 代码: #include<bits/stdc++.h> using namespace std; #define fi fir ...
- 【CF600E】 Lomsat gelral
CF600E Lomsat gelral Solution 考虑一下子树的问题,我们可以把一棵树的dfn序搞出来,那么子树就是序列上的一段连续的区间. 然后就可以莫队飞速求解了. 但是这题还有\(\T ...
- 【CodeForces】600 E. Lomsat gelral (dsu on tree)
[题目]E. Lomsat gelral [题意]给定n个点的树,1为根,每个点有一种颜色ci,一种颜色占领一棵子树当且仅当子树内没有颜色的出现次数超过它,求n个答案——每棵子树的占领颜色的编号和Σc ...
- 【CF600E】Lomsat gelral(dsu on tree)
[CF600E]Lomsat gelral(dsu on tree) 题面 洛谷 CF题面自己去找找吧. 题解 \(dsu\ on\ tree\)板子题 其实就是做子树询问的一个较快的方法. 对于子树 ...
随机推荐
- 关闭在chrome里使用双指前进后退页面的功能
defaults write com.google.Chrome AppleEnableSwipeNavigateWithScrolls -bool FALSE
- 完全用nosql轻松打造千万级数据量的微博系统
其实微博是一个结构相对简单,但数据量却是很庞大的一种产品.标题所说的是千万级数据量也并不是一千万条微博信息而已,而是千万级订阅关系之间发布.在看 我这篇文章之前,大多数人都看过sina的杨卫华大牛的微 ...
- 服务器初识、linux安装、linux初识
电脑硬件 电源 既然是人体的心脏,保障电源供应,就需要质量好的电源,生产环境中单个核心服务器最好是双电源AB线路. 一个接220V电路,一个可能接蓄电池UPS(不间断电源) cpu 常见品牌:Inte ...
- Mybatis框架学习总结-调用存储过程
设计需求 查询数据库,查询得到男性或女性的数量,如果传入的参数是0查询女性,否则查询男性. 准备数据库表和存储过程 1.准备person表: CREATE TABLE person( id INT P ...
- 使用selenium
1.安装谷歌浏览器 2.安装谷歌浏览器驱动 3.安装selenium包 4.测试 1.安装谷歌浏览器 2.安装谷歌浏览器驱动 打开 http://blog.csdn.net/huilan_ ...
- springboot设置返回值的编码
/** * @param params * @return 志诚阿福 来访问 */ @PostMapping(value = "/fromAFu", produces = &quo ...
- 【足迹C++primer】38、关联容器操作(2)
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/cutter_point/article/details/35244805 关联容器操作(2) map ...
- zabbix详解(一)
zabbix简介 zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案. zabbix能监视各种网络参数,保证服务器系统的安全运营:并提供柔软的通知机制以让系统管 ...
- 运输层协议--TCP及UDP协议
TCP及UDP协议 按照网络的五层分级结构来看,TCP及UDP位于运输层,故TCP及UDP是运输层协议.TCP协议--传输控制协议UDP协议--用户数据报协议 多路复用及多路分解 图多路复用及多路分解 ...
- 关于js中的取值问题
像这样是获取不到值的,弹出的消息是 underfined:<html><style type="text/css">input { border: 1px ...