zoukankan      html  css  js  c++  java
  • CodeForces 1009F.Dominant Indices【树上启发式合并】

    传送门

    题意

    给定一棵以 11 为根,nn 个节点的树。设 d(u,x)d(u,x) 为 uu 子树中到 uu 距离为 xx 的节点数。
    对于每个点,求一个最小的 kk,使得 d(u,k)d(u,k) 最大。

    题解

    和那个数颜色的题是一样的,就是一道标准的 dsu on tree 的模板题。当练手了。

    代码

    #include <bits/stdc++.h>
    #define xx first
    #define yy second
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> PII;
    const int N=1e6+10;
    const int M=1e6+10;
    int n,siz[N],dep[N],son[N],ans[N],cnt[N],Son,maxd;
    vector<int> g[N];
     
    void predfs(int u,int fa){
    	siz[u]=1;dep[u]=dep[fa]+1;
    	for(int v:g[u]){
    		if(v==fa) continue;
    		predfs(v,u);
    		siz[u]+=siz[v];
    		if(siz[v]>siz[son[u]]) son[u]=v;
    	}
    }
     
    void add(int u,int fa,int val){
    	cnt[dep[u]]+=val;
    	if(cnt[dep[u]]>cnt[maxd]||cnt[dep[u]]==cnt[maxd]&&dep[u]<maxd) maxd=dep[u];
    	for(int v:g[u]) if(v!=fa&&v!=Son) add(v,u,val);
    }
     
    void dfs(int u,int fa,bool keep){
    	for(int v:g[u]){
    		if(v==fa||v==son[u]) continue;
    		dfs(v,u,false);
    	}
    	if(son[u]) dfs(son[u],u,true);
    	Son=son[u];
    	add(u,fa,1);
    	ans[u]=maxd;
    	if(!keep) Son=0,add(u,fa,-1),maxd=0;
    }
     
    int main(){
    	scanf("%d",&n);
    	for(int i=1,u,v;i<n;i++){
    		scanf("%d%d",&u,&v);
    		g[u].push_back(v);
    		g[v].push_back(u);
    	}
    	predfs(1,0);
    	dfs(1,0,true);
    	for(int i=1;i<=n;i++) printf("%d
    ",ans[i]-dep[i]);
    	return 0;
    }
    
  • 相关阅读:
    设计模式
    工厂方法模式
    简单工厂模式
    tornado自定义Form组件
    tornado
    Tornado框架的知识系列
    Linux基本命令
    day2
    day1
    使用cp复制文件夹却不能打开
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/12611886.html
Copyright © 2011-2022 走看看