题意:求每一个子树存在最多颜色的颜色代号和(可重复)

本题是离线统计操作,因此可以直接合并重儿子已达到\(O(nlogn)\)的复杂度

PS.不知道什么是启发式合并的可以这样感受一下:进行树链剖分,分出重儿子和轻儿子,每次离线dfs时保留重儿子得出的贡献,清除轻儿子的贡献并重新遍历

(反正是一种取代树上莫队的简单粗暴玩意,但是效率贼tm好)

唯一不解的小细节是似乎我在轻儿子的撤销操作中更新tmp存在问题,改了另一种写法就A了

想不出反例,求指教

Update:看出来了,是我傻缺..

#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
using namespace std;
const int MAXN = 1e5+11;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],head[MAXN],tot;
int CLOCK,size[MAXN],st[MAXN],ed[MAXN],pre[MAXN];
int cntVal[MAXN],cntNum[MAXN],tmp,n;
bool vis[MAXN];
ll sum[MAXN],ans[MAXN],c[MAXN];
void init(){
memset(head,-1,sizeof head);
memset(cntVal,0,sizeof cntVal);
memset(cntNum,0,sizeof cntNum);
memset(sum,0,sizeof sum);
memset(vis,0,sizeof vis);
tmp=0;tot=0;CLOCK=0;
}
void add(int u,int v){
to[tot]=v;nxt[tot]=head[u];head[u]=tot++;
swap(u,v);
to[tot]=v;nxt[tot]=head[u];head[u]=tot++;
}
void prepare(int u,int p){
size[u]=1;
st[u]=++CLOCK;pre[CLOCK]=u;
erep(i,u){
int v=to[i];
if(v==p)continue;
prepare(v,u);
size[u]+=size[v];
}
ed[u]=CLOCK;
}
void dfs(int u,int p,bool keep){
int mx=0,son=-1;
erep(i,u){
int v=to[i];
if(v==p)continue;
if(size[v]>mx){
mx=size[v];
son=v;
}
}
erep(i,u){
int v=to[i];
if(v==p)continue;
if(v==son) continue;
dfs(v,u,0);
}
if(~son) dfs(son,u,1);
erep(i,u){
int v=to[i];
if(v==p)continue;
if(v==son)continue;
rep(j,st[v],ed[v]){
int o=pre[j];
sum[cntVal[c[o]]]-=c[o];
cntNum[cntVal[c[o]]]--;
cntVal[c[o]]++;
cntNum[cntVal[c[o]]]++;
sum[cntVal[c[o]]]+=c[o];
if(tmp<cntVal[c[o]]) tmp=cntVal[c[o]];
}
}
sum[cntVal[c[u]]]-=c[u];
cntNum[cntVal[c[u]]]--;
cntVal[c[u]]++;
cntNum[cntVal[c[u]]]++;
sum[cntVal[c[u]]]+=c[u];
if(tmp<cntVal[c[u]]) tmp=cntVal[c[u]]; ans[u]=sum[tmp]; if(!keep){
rep(i,st[u],ed[u]){
int v=pre[i];
sum[cntVal[c[v]]]-=c[v];
cntNum[cntVal[c[v]]]--;
//if(tmp==cntVal[c[v]]&&cntNum[cntVal[c[v]]]==0) tmp--;
cntVal[c[v]]--;
cntNum[cntVal[c[v]]]++;
sum[cntVal[c[v]]]+=c[v];
if(cntNum[tmp]==0) tmp--;
}
}
}
int main(){
while(cin>>n){
init();
rep(i,1,n) c[i]=read();
rep(i,1,n) if(!vis[c[i]]){
sum[0]+=c[i];
cntNum[0]++;
vis[c[i]]=1;
}
rep(i,1,n-1){
int u=read();
int v=read();
add(u,v);
}
prepare(1,-1);
dfs(1,-1,0);
rep(i,1,n){
if(i==n) println(ans[i]);
else printbk(ans[i]);
}
}
return 0;
}

Codeforces - 600E 树上启发式合并的更多相关文章

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

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

  2. Codeforces 208E - Blood Cousins(树上启发式合并)

    208E - Blood Cousins 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor.多次查询,给出 u k,问有多少个与 u 具有相同 k-ance ...

  3. 树上启发式合并(dsu on tree)学习笔记

    有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...

  4. 神奇的树上启发式合并 (dsu on tree)

    参考资料 https://www.cnblogs.com/zhoushuyu/p/9069164.html https://www.cnblogs.com/candy99/p/dsuontree.ht ...

  5. CF EDU - E. Lomsat gelral 树上启发式合并

    学习:http://codeforces.com/blog/entry/44351 E. Lomsat gelral 题意: 给定一个以1为根节点的树,每个节点都有一个颜色,问每个节点的子树中,颜色最 ...

  6. dsu on tree (树上启发式合并) 详解

    一直都没出过算法详解,昨天心血来潮想写一篇,于是 dsu on tree 它来了 1.前置技能 1.链式前向星(vector 建图) 2.dfs 建树 3.剖分轻重链,轻重儿子 重儿子 一个结点的所有 ...

  7. dsu on tree 树上启发式合并 学习笔记

    近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...

  8. hdu6191(树上启发式合并)

    hdu6191 题意 给你一棵带点权的树,每次查询 \(u\) 和 \(x\) ,求以 \(u\) 为根结点的子树上的结点与 \(x\) 异或后最大的结果. 分析 看到子树,直接上树上启发式合并,看到 ...

  9. csu1811(树上启发式合并)

    csu1811 题意 给定一棵树,每个节点有颜色,每次仅删掉第 \(i\) 条边 \((a_i, b_i)\) ,得到两颗树,问两颗树节点的颜色集合的交集. 分析 转化一下,即所求答案为每次删掉 \( ...

随机推荐

  1. SQL将表中某一类型的一列拼接成一行

    SELECT TypeName ,(SELECT ','+ UserName FROM [ContainerMembers] t WHERE TypeName= aa.TypeName FOR XML ...

  2. SqueezeNet:AlexNet-level Accuracy with 50x fewer parameters and less than 0.5Mb model size

    - Fire modules consisting of a 'squeeze' layer with 1*1 filters feeding an 'expand' layer with 1*1 a ...

  3. python2.7响应数据中unicode转中文

    print ("响应结果:%s" % r.content.decode('unicode_escape')) 一. 在爬虫抓取网页信息时常需要将类似"\u4eba\u75 ...

  4. sql 与 oracle 几个简单语法差别

    sql 与 oracle 之间的 语法差别. 简单的几个函数转换 sql->  Up_Time=getdate(),  isnull(), substring(),  charindex(), ...

  5. SQL Server 根据关键字和结束符提取字符串子串

    /* @info-待截取的字符串 @indexStr-截取子串的起始字符串 @split-截取子串的结束符号 列入依次传入 胸片:正常.心电图:异常,需要注意.血常规检查:正常. 心电图 '.' 返回 ...

  6. The method identifyUser(Arrays.asList("group001"), String, new HashMap<>()) is undefined for the type AipFace

    在使用百度云的人脸识别sdk时遇到了这个错误,网上百度不到解决的方法,当我浏览百度云的时候发现了这个 于是考虑到版本可能更新,出现了新的函数代替旧的函数,于是去查文档,文档链接如下 https://c ...

  7. oracle查询分区表中的数据

    select * from TABLE_NAME partition(分区名) T WHERE T.COL_NAME= 'XX';

  8. 网页控件很多时最好用绝对定位absolute

    否则动一个位置可能影响其他的,牵一发而动全身

  9. bzoj2395 [Balkan 2011]Timeismoney(最小乘积生成树+计算几何)

    题意 每条边有两个权值\(c,t\),请求出一颗生成树,使得\(\sum c\times \sum t\)最小 题解 为什么生成树会和计算几何扯上关系-- 对于每棵树,设\(x=c,y=t\),我们可 ...

  10. 洛谷P4559 [JSOI2018]列队(主席树)

    题面 传送门 题解 首先考虑一个贪心,我们把所有的人按\(a_i\)排个序,那么排序后的第一个人到\(k\),第二个人到\(k+1\),...,第\(i\)个人到\(k+i-1\),易证这样一定是最优 ...