• codeforces 600E Lomsat gelral


    题面:codeforces600E

    学习一下$dsu on tree$。。

    这个东西可以处理很多无修改子树问题,复杂度通常为$O(nlogn)$。

    主要操作是:我们先把整棵树链剖一下,然后每次先递归轻儿子,再递归重儿子。

    对于每棵子树,我们暴力加入整棵子树的贡献。如果是重儿子的子树则另外处理:加入贡献时不考虑加重儿子所在的子树,而在消除贡献时也不消除重儿子的子树,直到它成为某个点的轻儿子的子树的一部分时再消除贡献。

    复杂度:因为每个轻儿子最多被加入$O(logn)$次(递归轻儿子时$size$至少$/2$),每条重链最多只会被加入$O(logn)$次,所以复杂度是$O(nlogn)$的。

    说得有点玄学,还是看看代码吧。。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <queue>
    10 #include <stack>
    11 #include <map>
    12 #include <set>
    13 #define inf (1<<30)
    14 #define N (200010)
    15 #define il inline
    16 #define RG register
    17 #define ll long long
    18 
    19 using namespace std;
    20 
    21 struct edge{ int nt,to; }g[N<<1];
    22 
    23 int head[N],col[N],son[N],sz[N],c[N],n,num,Mx,flag;
    24 ll ans[N],Sum;
    25 
    26 il int gi(){
    27     RG int x=0,q=1; RG char ch=getchar();
    28     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    29     if (ch=='-') q=-1,ch=getchar();
    30     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    31     return q*x;
    32 }
    33 
    34 il void insert(RG int from,RG int to){
    35     g[++num]=(edge){head[from],to},head[from]=num; return;
    36 }
    37 
    38 il void dfs1(RG int x,RG int p){
    39     sz[x]=1; RG int v;
    40     for (RG int i=head[x];i;i=g[i].nt){
    41     v=g[i].to; if (v==p) continue;
    42     dfs1(v,x),sz[x]+=sz[v];
    43     if (sz[son[x]]<=sz[v]) son[x]=v;
    44     }
    45     return;
    46 }
    47 
    48 il void add(RG int x,RG int p,RG int val){
    49     col[c[x]]+=val; RG int v;
    50     if (Mx<col[c[x]]) Mx=col[c[x]],Sum=c[x];
    51     else if (Mx==col[c[x]]) Sum+=c[x];
    52     for (RG int i=head[x];i;i=g[i].nt){
    53     v=g[i].to; if (v==p || v==flag) continue;
    54     add(v,x,val);
    55     }
    56     return;
    57 }
    58 
    59 il void dfs2(RG int x,RG int p,RG int fg){
    60     RG int v;
    61     for (RG int i=head[x];i;i=g[i].nt){
    62     v=g[i].to; if (v!=p && v!=son[x]) dfs2(v,x,1);
    63     }
    64     if (son[x]) dfs2(son[x],x,0),flag=son[x];
    65     add(x,p,1),flag=0,ans[x]=Sum;
    66     if (fg) add(x,p,-1),Mx=Sum=0; return;
    67 }
    68 
    69 int main(){
    70 #ifndef ONLINE_JUDGE
    71     freopen("600E.in","r",stdin);
    72     freopen("600E.out","w",stdout);
    73 #endif
    74     n=gi();
    75     for (RG int i=1;i<=n;++i) c[i]=gi();
    76     for (RG int i=1,u,v;i<n;++i)
    77     u=gi(),v=gi(),insert(u,v),insert(v,u);
    78     dfs1(1,0),dfs2(1,0,1);
    79     for (RG int i=1;i<=n;++i) printf("%I64d ",ans[i]);
    80     return 0;
    81 }
  • 相关阅读:
    Steal 偷天换日 题解(From luoguBlog)
    Hibernat之关系的处理多对多
    Hibernat之关系的处理一对一处理
    Hibernat之关系的处理一对多/多对一
    Hibernate 一对多注解 mappedby 作用
    hibernate之使用Annotation注解搭建项目
    暑假学习第八周
    暑假学习第七周
    java学习第六周
    暑假学习第五周
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7227154.html
Copyright © 2020-2023  润新知