• [dsu on tree] Codeforces 600E Lomsat gelral


    题目大意

    • 给出一个树,求出每个节点的子树中出现次数最多的颜色的编号和

    题解

    • 这是一道dsu on tree的模板题
    • 那dsu on tree到底是个啥东西呢
    • dsu on tree是一种类似暴力的做法,用来解决一类树上询问的问题。一般有两种特征:①只有对子树询问 ②没有修改操作 

      dsu on tree运用了类似轻重链剖分把复杂度给降到O(nlogn)

      算法流程:先dfs处理出每个父节点的重轻儿子,然后统计的时候,先递归处理每个轻儿子的贡献,同时消除递归产生的影响,然后递归重儿子,不消除递归的影响,再统计所有轻儿子对答案的影响,最后更新该节点的答案和删除所有轻儿子对答案的影响

      我们来证明一下这个东东的复杂度,我们考虑一个点会被访问几次,发现只有两种情况,一种是暴力统计轻边的时候访问到,因为一个点到根的轻边数量不会多于logn条,所以次数<logn;第二种是通过重边被访问到显然每个点只会被访问一次。综上所述,如果一个点所贡献的复杂度为O(1)的话,总复杂度为O(nlogn)

       
    • 然后我们就可以发现用上面这个东西,可以很暴力的解决这个问题

    代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <vector>
     5 #define N 100010
     6 #define ll long long
     7 using namespace std;
     8 int n,mx,Son,col[N],son[N],sz[N],cnt[N];
     9 ll sum,ans[N];
    10 vector<int>Q[N];
    11 int read()
    12 {
    13     char c=getchar(); int x=0,f=1;
    14     while (c<'0'||c>'9') { if(c == '-') f=-1;c=getchar(); }
    15     while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    16     return x*f;
    17 }
    18 void add(int x,int fa,int val)
    19 {
    20     cnt[col[x]]+=val;
    21     if (cnt[col[x]]>mx) mx=cnt[col[x]],sum=col[x]; else if (cnt[col[x]]==mx) sum+=(ll)col[x];
    22     for (int i=0;i<Q[x].size();i++) if (Q[x][i]!=fa&&Q[x][i]!=Son) add(Q[x][i],x,val);
    23 }
    24 void dfs1(int x,int fa)
    25 {
    26     sz[x]=1;
    27     for (int i=0;i<Q[x].size();i++)
    28         if (Q[x][i]!=fa)
    29         {
    30             dfs1(Q[x][i],x),sz[x]+=sz[Q[x][i]];
    31             if (sz[Q[x][i]]>sz[son[x]]) son[x]=Q[x][i];
    32         }
    33 }
    34 void dfs2(int x,int fa,int op)
    35 {
    36     for (int i=0;i<Q[x].size();i++) if (Q[x][i]!=fa&&Q[x][i]!=son[x]) dfs2(Q[x][i],x,0);
    37     if (son[x]) dfs2(son[x],x,1),Son=son[x];
    38     add(x,fa,1),Son=0,ans[x]=sum;
    39     if (!op) add(x,fa,-1),sum=0,mx=0;
    40 }
    41 int main()
    42 {
    43     n=read();
    44     for (int i=1;i<=n;i++) col[i]=read();
    45     for (int i=1,x,y;i<n;i++) x=read(),y=read(),Q[x].push_back(y),Q[y].push_back(x);
    46     dfs1(1,0),dfs2(1,0,0);
    47     for (int i=1;i<=n;i++) printf("%lld ",ans[i]);
    48 }
  • 相关阅读:
    Mac Studio 的内部存储可更换但不可升级
    Mac电脑的激活日期如何查询?
    隐藏在sketch的10个实用技巧,学会就是赚到!
    Macbook如何查看是M1芯片还是inter芯片?
    如何使用Photoshop2022中的背景图层?
    如何在 Illustrator 中转换图稿?
    .NET 代码整洁手册
    django修改model内容生效
    svn add 子目录文件目录无法递归
    debian9使用rsync拉取代码
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11185918.html
Copyright © 2020-2023  润新知