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\)板子题 其实就是做子树询问的一个较快的方法. 对于子树 ...
随机推荐
- point in polygon algorithm
Point-In-Polygon Algorithm — Determining Whether A Point Is Inside A Complex Polygon © 1998,2006,200 ...
- 001-linux scp文件拷贝
scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下速度.当你服务器 ...
- 页面优化——减少HTTP请求数
1.关于减少http请求数 关于减少http请求数,是前端开发性能优化的一个非常重要方面,所以在基本所有的优化原则里,都有这一条原则:减少http请求数. 先不考虑其他的,我们先考虑为什么减少http ...
- SQL Server扩展属性的增、删、改、查
使用 sql 语句创建表时,可以使用系统存储过程 sp_addextendedproperty 给字段添加描述说明. sp_addextendedproperty 语法: sp_addextended ...
- ruby中的可调用对象--方法
上一篇讲了ruby中的可调用对象proc和lambda,他们都是块转换成的对象.ruby中的可调用对象还有方法.通过使用method方法,并且以方法名作为参数(字符串或者符号),就可以得到一个方法对象 ...
- AtCoder Regular Contest 080 D - Grid Coloring
地址:http://arc080.contest.atcoder.jp/tasks/arc080_b 题目: D - Grid Coloring Time limit : 2sec / Memory ...
- hdp (ambari) 集成hue
ambari-server resetambari-admin-password-reset https://github.com/EsharEditor/ambari-hue-service可以基于 ...
- selenium+python—实现自动化测试基本思路
测试是一个贯穿于整个开发过程的连续过程,测试最基本的原理就是比较预期结果是否与实际执行结果相同,如果相同则测试成功,否则测试失败. 为了让单元测试代码能够被测试和维护人员更容易地理解,最好的解决办法是 ...
- python3_Logging模块详解
python的logging模块提供了通用的日志系统,可以方便第三方模块或应用使用. 简单使用 import logging # logging.config.fileConfig("./l ...
- SpringMvc接受特殊符号参数被转义
WEB开发时,在前端通过get / post 方法传递参数的时候 如果实参附带特殊符号,后端接收到的值中特殊符号就会被转义 例如该请求: http://localhost:10001/demo/in ...