zoukankan      html  css  js  c++  java
  • CF600E Lomsat gelral(dsu on tree)

    一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,如果一个子树中某种颜色的出现次数最多,则称这棵子树被这种颜色占领(可能被多种颜色占领),问以每一个节点为根的子树,占领它的颜色的编号之和

    这题的做法好像是一个叫做dsu on tree的东西(dsu似乎是并查集的缩写?然而和并查集没什么关系啊……)

    这题目虽然dfs序套莫队也能做,不过我们考虑一下暴力的方法

    我们在统计节点u之前,把u的所有子树的贡献都加入答案,然后在暴力把所有的贡献都清楚

    然而这样会有很多的无用的删除操作

    我们考虑先把原树给轻重链剖分,然后统计子树贡献的时候,在处理完轻儿子的答案之后,把他们的影响给消除,但处理完重儿子的答案之后,不必把影响消除

    这样的话顺序就是先处理轻儿子的答案并消除影响,然后处理重儿子,保留影响,再去处理一遍轻儿子来求出当前子树的答案

    因为轻重链剖分之后一个点到根的路径上最多有$O(logn)$条轻边,所以每个节点只会被统计与删除$O(logn)$次,总复杂度就是$O(nlogn)$

    板子(?)抄zcy的

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #define ll long long
     5 using namespace std;
     6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     7 char buf[1<<21],*p1=buf,*p2=buf;
     8 int read(){
     9     #define num ch-'0'
    10     char ch;bool flag=0;int res;
    11     while(!isdigit(ch=getc()))
    12     (ch=='-')&&(flag=true);
    13     for(res=num;isdigit(ch=getc());res=res*10+num);
    14     (flag)&&(res=-res);
    15     #undef num
    16     return res;
    17 }
    18 char sr[1<<21],z[20];int C=-1,Z;
    19 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    20 void print(ll x){
    21     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    22     while(z[++Z]=x%10+48,x/=10);
    23     while(sr[++C]=z[Z],--Z);sr[++C]=' ';
    24 }
    25 const int N=2e5+5;
    26 int head[N],Next[N<<1],ver[N<<1],tot;
    27 void add(int u,int v){
    28     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
    29 }
    30 int n,c[N],val[N],sz[N],son[N];ll ans[N];
    31 void dfs1(int u,int fa=0){
    32     sz[u]=1;
    33     for(int i=head[u];i;i=Next[i]){
    34         int v=ver[i];
    35         if(v!=fa){
    36             dfs1(v,u),sz[u]+=sz[v];
    37             if(sz[son[u]]<sz[v]) son[u]=v;
    38         }
    39     }
    40 }
    41 bool vis[N];int mx=0;ll sum=0;
    42 void update(int u,int fa,int k){
    43     c[val[u]]+=k;
    44     if(k>0&&c[val[u]]>=mx){
    45         if(c[val[u]]>mx) sum=0,mx=c[val[u]];
    46         sum+=val[u];
    47     }
    48     for(int i=head[u];i;i=Next[i])
    49     if(ver[i]!=fa&&!vis[ver[i]]) update(ver[i],u,k);
    50 }
    51 void dfs2(int u,int fa=0,bool used=0){
    52     for(int i=head[u];i;i=Next[i]){
    53         int v=ver[i];if(v!=fa&&v!=son[u]) dfs2(v,u);
    54     }
    55     if(son[u]) dfs2(son[u],u,1),vis[son[u]]=1;
    56     update(u,fa,1),ans[u]=sum;
    57     if(son[u]) vis[son[u]]=0;
    58     if(!used) update(u,fa,-1),mx=sum=0;
    59 }
    60 int main(){
    61 //    freopen("testdata.in","r",stdin);
    62     n=read();
    63     for(int i=1;i<=n;++i) val[i]=read();
    64     for(int i=1;i<n;++i){
    65         int u=read(),v=read();add(u,v),add(v,u);
    66     }
    67     dfs1(1),dfs2(1);
    68     for(int i=1;i<=n;++i) print(ans[i]);
    69     return Ot(),0;
    70 }
  • 相关阅读:
    UVa 1252 20个问题
    HDU 2196 Computer
    HDU 1520 Anniversary party
    HDU 2066 一个人的旅行
    UVa 10048 噪音恐惧症(Floyd)
    UVa 247 电话圈(Floyd传递闭包)
    HDU 2544 最短路(Dijkstra)
    HDU 1548 A strange lift (Dijkstra)
    UVa 1151 买还是建
    UVa 1395 苗条的生成树(Kruskal+并查集)
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9815915.html
Copyright © 2011-2022 走看看