码迷,mamicode.com
首页 > 其他好文 > 详细

启发式合并

时间:2020-04-28 00:47:46      阅读:58      评论:0      收藏:0      [点我收藏+]

标签:bsp   get   mes   style   std   产生   else   href   col   

Lomsat gelral

 CodeForces - 600E 

题意:给你一个树,每个节点有一个颜色,求每个节点出现次数最大颜色编号和。

考虑每个点都必然有多颗子树,统计该点的答案时必然要合并多个子树。
启发式合并就是把小的往大的合并,这样保证log(n)的复杂度。
这个题考虑这样做法:
对于每一个点,
1 . 统计出所有轻儿子的答案,不计入当前点的答案,
2 . 统计重儿子的答案,计入当前点的答案,
3 . 再回头扫一遍轻儿子,将轻儿子的答案和重儿子的答案合并,最终得到当前点的答案。
这样合并保证了复杂度。
但对于每一个轻儿子,当处理完之后,就要删除贡献,因为会对其他轻儿子产生影响。
技术图片
/*
CF600E   
启发式合并  复杂度 n*(log(n) 
*/
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int son[N],col[N],head[N],size[N];
long long cnt[N],ans[N];
struct edge{int v,next;}e[N<<2];
int ecnt,n,maxc,thisson;
long long thissum;
void init(){
    memset(head,-1,sizeof head);
    memset(son,0,sizeof son);
    maxc=ecnt=thisson=thissum=0;
}
void add(int u,int v){
    e[ecnt].v=v;e[ecnt].next=head[u];head[u]=ecnt++;
}
void dfs_size(int u,int fa){//剖分树链
    size[u]=1;
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==fa)continue;
        dfs_size(v,u);
        size[u]+=size[v];
        if(size[v]>size[son[u]])son[u]=v;
    }
}
void Count(int u,int fa,int val){//累积或删除贡献
    cnt[col[u]]+=val;
    if(cnt[col[u]]>maxc){
        maxc=cnt[col[u]];
        thissum=col[u];
    }
    else if(cnt[col[u]]==maxc)thissum+=col[u];
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==fa||v==thisson)continue;
        Count(v,u,val);
    }
}
void dfs_ans(int u,int fa,bool keep){//统计每个点的答案,保留或者不保留贡献
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==fa||v==son[u])continue;
        dfs_ans(v,u,false);
    }
    if(son[u]){
        dfs_ans(son[u],u,true);
        thisson=son[u];
    }
    Count(u,fa,1);
    thisson=0;
    ans[u]=thissum;
    if(!keep){
        Count(u,fa,-1);
        thissum=maxc=0;
    }
}
int main(){
    scanf("%d",&n);
    init();
    for(int i=1;i<=n;i++)scanf("%d",&col[i]);
    for(int i=1,u,v;i<n;i++){
        scanf("%d %d",&u,&v);
        add(u,v);add(v,u);
    }
    dfs_size(1,-1);
    dfs_ans(1,-1,0);
    for(int i=1;i<=n;i++)printf("%I64d ",ans[i]);
    return 0;
}
View Code

 

启发式合并

标签:bsp   get   mes   style   std   产生   else   href   col   

原文地址:https://www.cnblogs.com/littlerita/p/12791208.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!