• CF600E Lomsat gelral(dsu on tree)


    Lomsat gelral

    题目描述

    一个NN个节点的有根树(点11为根),节点从11到NN编号,每个节点有一个颜色C_iCi

    对于一个以xx为根的子树,我们认为颜色cc在这个子树中出现的次数是最多的,则认为cc支配了这个子树。

    如果有多个颜色的次数相同并且都为最大,则他们都支配了这个子树。

    对每个节点xx,输出所有支配他的子树的颜色的编号之和。

    输入格式

    第一行一个整数n,

    接下来一行n个整数Ci,

    接下来n-1行,每行两个整数x,y,表示x和y有一条边。

    输出格式

    输出一行n个数,第i个数为节点i的答案。


    dsu on tree入门题

    dsu on tree(转)

    套到下面的模板里就好辣

    void dfs1(int x,int fa){
        siz[x]=1;
        for(auto i:g[x]) if(i!=fa){
            dfs1(i,x); siz[x]+=siz[i];
            if(siz[i]>siz[big[x]]) big[x]=i;//找重儿子
        }
    }
    void draw(int x,int fa,int k){
        // ....
        for(auto i:g[x]) if(i!=fa&&!vis[i]) draw(i,x,k);
    }
    void dfs2(int x,int fa,bool is){
        for(auto i:g[x]) if(i!=fa&&i!=big[x]) dfs2(i,x,0);
        if(big[x]) dfs2(big[x],x,1),vis[big[x]]=1;
        draw(x,fa,1); 
        if(big[x]) vis[big[x]]=0;
        if(!is) draw(x,fa,-1);//保留重子树的数据
    }

    复杂度$O(nlogn)$


    #include<cstdio>
    #include<vector>
    using namespace std;
    void read(int &x){
        char c=getchar();x=0;
        while(c<'0'||c>'9') c=getchar();
        while('0'<=c&&c<='9') x=x*10+c-48,c=getchar();
    }
    #define N 1000005
    int n,siz[N],big[N],cr[N],c[N],mx;
    long long ans[N],sum;
    bool vis[N];
    vector <int> g[N];
    void dfs1(int x,int fa){
        siz[x]=1;
        for(auto i:g[x]) if(i!=fa){
            dfs1(i,x); siz[x]+=siz[i];
            if(siz[i]>siz[big[x]]) big[x]=i;
        }
    }
    void draw(int x,int fa,int k){
        c[cr[x]]+=k;
        if(k>0&&c[cr[x]]>=mx){
            if(c[cr[x]]>mx) sum=0;
            mx=c[cr[x]]; sum+=cr[x];
        }
        for(auto i:g[x]) if(i!=fa&&!vis[i]) draw(i,x,k);
    }
    void dfs2(int x,int fa,bool is){
        for(auto i:g[x]) if(i!=fa&&i!=big[x]) dfs2(i,x,0);
        if(big[x]) dfs2(big[x],x,1),vis[big[x]]=1;
        draw(x,fa,1); ans[x]=sum;
        if(big[x]) vis[big[x]]=0;
        if(!is) draw(x,fa,-1),sum=mx=0;
    }
    int main(){
        read(n);
        for(int i=1;i<=n;++i) read(cr[i]);
        for(int i=1,p,q;i<n;++i){
            read(p); read(q);
            g[p].push_back(q);
            g[q].push_back(p);
        }dfs1(1,0); dfs2(1,0,1);
        for(int i=1;i<=n;++i) printf("%lld ",ans[i]);
        return 0;
    }
  • 相关阅读:
    php 替换二维数组的 key
    全选功能
    向数组中添加含有下标的元素
    判断一个进程是否在执行中
    初识 Nginx
    原生JS中DOM节点相关API合集
    工作中经常用到github上优秀、实用、轻量级、无依赖的插件和库
    Unsupported major.minor version ... JDK具体对应版本
    Scala常用命令
    使用nexus搭建maven私服教程详解
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10946109.html
Copyright © 2020-2023  润新知