题目链接

dsu on tree详见这

\(Description\)

给定一棵树。求以每个点为根的子树中,出现次数最多的颜色的和。

\(Solution\)

dsu on tree模板题.

用\(sum[i]\)表示出现次数为\(i\)的颜色的和,\(cnt[i]\)表示出现次数为\(i\)的颜色有多少个(其实用个\(Max\)表示当前最多的次数,和每种颜色出现次数\(tm[i]\)就好了),然后。。就这样了。。

可以用DFS序代替DFS减少一些常数。


再写一遍dsu on tree大体过程:(设当前点为\(x\))

计算轻儿子子树的答案,并删掉轻儿子的贡献(大多数时候);

计算重儿子子树的答案,保留重儿子的贡献(有时候不需要?);

加入\(x\)轻儿子子树的贡献;

得到\(x\)的答案;

如果\(x\)不是重儿子,则删掉它整个子树的贡献(本题直接将\(Max,Sum\)清0就好了)。

复杂度证明:每个点会在它上面的每条轻边处暴力统计一次。而每个点到根节点的路径上只有\(O(\log n)\)条轻边。


优化:(DFS序)

//62ms	13400KB
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5; int skip,Enum,H[N],nxt[N<<1],to[N<<1],Max,col[N],sz[N],son[N],tm[N],A[N],L[N],R[N];
LL Sum,Ans[N];
char IN[MAXIN],*SS=IN,*TT=IN; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AE(int u,int v)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
void DFS1(int x,int fa)
{
static int Index=0;
A[L[x]=++Index]=x;
int mx=0; sz[x]=1;
for(int i=H[x],v; i; i=nxt[i])
if((v=to[i])!=fa)
{
DFS1(v,x), sz[x]+=sz[v];
if(sz[v]>mx) mx=sz[v], son[x]=v;
}
R[x]=Index;
}
inline void Add(int c)
{
if(++tm[c]>Max) Max=tm[c], Sum=c;
else if(tm[c]==Max) Sum+=c;
}
void Solve(int x,int fa,int keep)
{
for(int i=H[x]; i; i=nxt[i])
if(to[i]!=fa && to[i]!=son[x]) Solve(to[i],x,0);
if(son[x]) Solve(son[x],x,1); Add(col[x]);
for(int i=H[x],v; i; i=nxt[i])
if((v=to[i])!=fa && v!=son[x])
for(int j=L[v]; j<=R[v]; ++j) Add(col[A[j]]);
Ans[x]=Sum;
if(!keep)
{
Max=Sum=0;
for(int i=L[x]; i<=R[x]; ++i) --tm[col[A[i]]];
}
} int main()
{
int n=read();
for(int i=1; i<=n; ++i) col[i]=read();
for(int i=1; i<n; ++i) AE(read(),read());
DFS1(1,1), Solve(1,1,1);
for(int i=1; i<=n; ++i) printf("%I64d ",Ans[i]); return 0;
}

未优化:

//93ms	9100KB
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5; int skip,Enum,H[N],nxt[N<<1],to[N<<1],Max,col[N],sz[N],son[N],tm[N];
LL Sum,Ans[N];
char IN[MAXIN],*SS=IN,*TT=IN; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AE(int u,int v)
{
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
void DFS1(int x,int fa)
{
int mx=0; sz[x]=1;
for(int i=H[x],v; i; i=nxt[i])
if((v=to[i])!=fa)
{
DFS1(v,x), sz[x]+=sz[v];
if(sz[v]>mx) mx=sz[v], son[x]=v;
}
}
void Add(int x,int fa)
{
if(++tm[col[x]]>Max) Max=tm[col[x]], Sum=col[x];
else if(tm[col[x]]==Max) Sum+=col[x];
for(int i=H[x]; i; i=nxt[i])
if(to[i]!=fa && to[i]!=skip) Add(to[i],x);
}
void Del(int x,int fa)
{
--tm[col[x]];
for(int i=H[x]; i; i=nxt[i])
if(to[i]!=fa) Del(to[i],x);
}
void Solve(int x,int fa,int keep)
{
for(int i=H[x]; i; i=nxt[i])
if(to[i]!=fa && to[i]!=son[x]) Solve(to[i],x,0);
if(son[x]) Solve(son[x],x,1), skip=son[x];
Add(x,fa), Ans[x]=Sum, skip=0;
if(!keep) Max=Sum=0, Del(x,fa);
} int main()
{
int n=read();
for(int i=1; i<=n; ++i) col[i]=read();
for(int i=1; i<n; ++i) AE(read(),read());
DFS1(1,1), Solve(1,1,1);
for(int i=1; i<=n; ++i) printf("%I64d ",Ans[i]); return 0;
}

Codeforces.600E.Lomsat gelral(dsu on tree)的更多相关文章

  1. Codeforces 600E. Lomsat gelral(Dsu on tree学习)

    题目链接:http://codeforces.com/problemset/problem/600/E n个点的有根树,以1为根,每个点有一种颜色.我们称一种颜色占领了一个子树当且仅当没有其他颜色在这 ...

  2. CF 600E. Lomsat gelral(dsu on tree)

    解题思路 \(dsu\) \(on\) \(tree\)的模板题.暴力而优雅的算法,轻儿子的信息暴力清空,重儿子的信息保留,时间复杂度\(O(nlogn)\) 代码 #include<iostr ...

  3. Codeforces 600E - Lomsat gelral(树上启发式合并)

    600E - Lomsat gelral 题意 给出一颗以 1 为根的树,每个点有颜色,如果某个子树上某个颜色出现的次数最多,则认为它在这课子树有支配地位,一颗子树上,可能有多个有支配的地位的颜色,对 ...

  4. Codeforces 600E Lomsat gelral(dsu on tree)

    dsu on tree板子题.这个trick保证均摊O(nlogn)的复杂度,要求资瓷O(1)将一个元素插入集合,清空集合时每个元素O(1)删除.(当然log的话就变成log^2了) 具体的,每次先遍 ...

  5. Codeforces 600E - Lomsat gelral 「$Dsu \ on \ tree$模板」

    With $Dsu \ on \ tree$ we can answer queries of this type: How many vertices in the subtree of verte ...

  6. 【CodeForces】600 E. Lomsat gelral (dsu on tree)

    [题目]E. Lomsat gelral [题意]给定n个点的树,1为根,每个点有一种颜色ci,一种颜色占领一棵子树当且仅当子树内没有颜色的出现次数超过它,求n个答案——每棵子树的占领颜色的编号和Σc ...

  7. codeforces 600E Lomsat gelral

    题面:codeforces600E 学习一下$dsu \ on \ tree$.. 这个东西可以处理很多无修改子树问题,复杂度通常为$O(nlogn)$. 主要操作是:我们先把整棵树链剖一下,然后每次 ...

  8. cf600E. Lomsat gelral(dsu on tree)

    题意 题目链接 给出一个树,求出每个节点的子树中出现次数最多的颜色的编号和 Sol dsu on tree的裸题. 一会儿好好总结总结qwq #include<bits/stdc++.h> ...

  9. Codeforces 600E Lomsat gelral (树上启发式合并)

    题目链接 Lomsat gelral 占坑……等深入理解了再来补题解…… #include <bits/stdc++.h> using namespace std; #define rep ...

随机推荐

  1. V4L2应用程序框架【转】

    转自:https://www.cnblogs.com/hzhida/archive/2012/05/29/2524397.html V4L2是V4L的升级版本,linux下视频设备程序提供了一套接口规 ...

  2. Linux 入门记录:十二、Linux 权限机制【转】

    转自:https://www.cnblogs.com/mingc/p/7591287.html 一.权限 权限是操作系统用来限制资源访问的机制,权限一般分为读.写.执行. 系统中每个文件都拥有特定的权 ...

  3. ES系列十三、Elasticsearch Suggester API(自动补全)

    1.概念 1.补全api主要分为四类 Term Suggester(纠错补全,输入错误的情况下补全正确的单词) Phrase Suggester(自动补全短语,输入一个单词补全整个短语) Comple ...

  4. Centos6.5使用yum安装mysql——快速上手必备

    第1步.yum安装mysql [root@stonex ~]#  yum -y install mysql-server 安装结果: Installed:     mysql-server.x86_6 ...

  5. mysql主从配置 转自http://www.cnblogs.com/sustudy/p/4174189.html

    1.确保主数据库与从数据库一模一样. 例如:主数据库里的a的数据库里有b,c,d表,那从数据库里的就应该有一个模子刻出来的a的数据库和b,c,d表 2.在主数据库上创建同步账号. GRANT REPL ...

  6. Android Studio安装apk失败

    可能的情况 手机上已经安装了应用或者应用卸载不彻底 解决办法: adb uninstall yourpackagename 如果uninstall失败,可以考虑 clean一下Android Stud ...

  7. S5PV210的根文件系统制作

    一.移植BusyBox1.下载BusyBox的源代码下载地址:http://www.busybox.net/downloads/,此处下载busybox-1.20.2.tar.bz2.2.解压并进入目 ...

  8. AdvStringGrid 标题头 加粗的问题

    当AdvStringGrid1.RowCount = 1的时候,会是下面这样: 当AdvStringGrid1.RowCount = 2 时 才是正确的:

  9. Laravel 返回数据库中的随机一行数据

    最佳方式 $total = Book::count() - 1; $skip = mt_rand(0, $total); $item = Book::select('name', 'author_id ...

  10. 欧拉函数,打表求欧拉函数poj3090

    欧拉函数 φ(n) 定义:[1,N]中与N互质的数的个数 //互质与欧拉函数 /* 求欧拉函数 按欧拉函数计算公式,只要分解质因数即可 */ int phi(int n){ int ans=n; ;i ...