zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    分享一个动态生成RDLC报表的类
    第一次写这么长的js
    [SpringCloud]Gateway入门
    [SpringCloud]Hystrix
    [SpringCloud]Eureka+OpenFeign
    [Java]Socket API编写一个简单的私聊和群聊
    JVM内存分区和各分区溢出测试
    使用Python操作neo4j和画柱状图
    JDK1.8 HashMap为什么在链表长度为8的时候转红黑树,为啥不能是9是10?
    Redis过期策略
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11185918.html
Copyright © 2011-2022 走看看