• 【CF600E】Lomsat gelral(DSU on Tree板子题)


    点此看题面

    • 给定一棵(n)个点的树,每个点上有一个数。
    • 对于每个点,求其子树内所有众数之和。
    • (nle10^5)

    (DSU on Tree)

    对于这种子树询问的问题,很容易想到(DSU on Tree)

    其实这道题就是一个板子题吧。

    考虑加入或删除一种颜色最多使众数的出现次数变化(1),因此只要记录每种数的出现次数,并对每种出现次数开个桶即可维护出答案。

    代码:(O(nlogn))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define LL long long
    #define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
    using namespace std;
    int n,a[N+5],ee,lnk[N+5];struct edge {int to,nxt;}e[N<<1];
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
    	int OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
    	I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    	Tp I void write(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc(' ');}
    }using namespace FastIO;
    int g[N+5],sz[N+5];I void Init(CI x=1,CI lst=0)//初始化,求出重儿子
    {
    	sz[x]=1;for(RI i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&
    		(Init(e[i].to,x),sz[x]+=sz[e[i].to],sz[e[i].to]>sz[g[x]]&&(g[x]=e[i].to));
    }
    #define A(x) (!s[++c[x]]&&++p,s[c[x]]+=x)//增加x
    #define D(x) (!(s[c[x]--]-=x)&&--p)//减小x
    int p,c[N+5];LL s[N+5];I void T(CI x,CI lst,CI op)//把x子树内全部加入/删除
    {
    	op?A(a[x]):D(a[x]);for(RI i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&(T(e[i].to,x,op),0);
    }
    LL ans[N+5];I void DSU(CI x=1,CI lst=0)//DSU on Tree
    {
    	RI i;for(i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&e[i].to^g[x]&&(DSU(e[i].to,x),T(e[i].to,x,0),0);//先做轻儿子,做一次清一次
    	if(g[x]) for(DSU(g[x],x),i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&e[i].to^g[x]&&(T(e[i].to,x,1),0);//最后做重儿子,并加上所有轻儿子
    	A(a[x]),ans[x]=s[p];//加上当前点,求出当前点的答案
    }
    int main()
    {
    	RI i,x,y;for(read(n),i=1;i<=n;++i) read(a[i]);for(i=1;i^n;++i) read(x,y),add(x,y),add(y,x);
    	for(Init(),DSU(),i=1;i<=n;++i) write(ans[i]);return clear(),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    (转载)博客园如何转载别人的文章
    python实现凯撒密码、凯撒加解密算法
    python新手学习可变和不可变对象
    Pycharm中配置远程Docker运行环境的教程图解
    python新手学习使用库
    python的help函数如何使用
    python编写softmax函数、交叉熵函数实例
    python能开发游戏吗
    python属于解释语言吗
    python的控制结构之For、While、If循环问题
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF600E.html
Copyright © 2020-2023  润新知