• AGC009 题解


    D. Uninity

    考虑这棵树形成的过程:初始都为 \(0\),每次合并时变为 \(k\) ,我们则将合并中心打上 \(k\) 的标记。结束时每个点上都有标记,这些标记有性质:对于不同的两点 \(u,v\),若 \(tag_u=tag_v\),则在 \(u,v\) 的路径上存在一点的 \(tag\) 大于它们。可以发现这也是冲要条件。

    现在我们需要让最大的 \(tag\) 最小。考虑贪心地从叶子往根(随意钦定)选。记显然每个都选最小可行的可以保证正确性。记 \(s_x\) 集合表示在 \(x\) 的子树中已经存在且到 \(x\) 还没有比它大的集合。

    1. \(c\in child_x\),则 \(tag_x\notin s_c\)

    2. \(c_1,c_2\in child_x\),则 \(tag_x>\max(s_{c_1}\cap s_{c_2})\)

    若不满足 \(1\),则存在其子树中一点到 \(x\) 不满足。

    若不满足 \(2\),则存在两个不同子树中的点通过 \(x\) 连起来而不满足。

    此时我们已经知道了 \(tag_x\),考虑由子树信息推出 \(s_x\)。我们发现所有小于 \(tag_x\) 的都可取了,所有大于 \(tag_x\) 且原来就不可取的还是不可取,且 \(tag_x\) 不可取。

    #include<bits/stdc++.h>
    using namespace std;
    #define inf 1e9
    const int maxn=2e5+10;
    const int mod=1e9+7;
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    	return x*f;
    }
    int n,m,ans,lab[maxn],s[maxn];
    int beg[maxn],nex[maxn],to[maxn],e;
    inline void add(int x,int y){
    	nex[++e]=beg[x];beg[x]=e;to[e]=y;
    	nex[++e]=beg[y];beg[y]=e;to[e]=x;
    }
    inline void dfs(int x,int fa){
    	int tt=0;
    	for(int i=beg[x];i;i=nex[i]){
    		int t=to[i];
    		if(t==fa)continue;
    		dfs(t,x);
    		tt|=s[x]&s[t];
    		s[x]|=s[t];
    	}
    	int k=tt?32-__builtin_clz(unsigned(tt)):0;
    	lab[x]=__builtin_ctz(unsigned((s[x]|((1<<k)-1))+1));
    	s[x]=(s[x]>>lab[x]|1)<<lab[x];
    }
    int main(){
    	n=read();
    	for(int i=1,x,y;i<n;i++)
    		x=read(),y=read(),add(x,y);
    	dfs(1,0);
    	for(int i=1;i<=n;i++)
    		ans=max(ans,lab[i]);
    	printf("%d\n",ans);
        return 0;
    }
    
    
  • 相关阅读:
    【luogu P1307 数字反转】 题解
    【luogu P1111 公路修建】 题解
    字符串与正则运算
    Java 正则表达式的总结和一些小例子
    js -history.back(-1)和history.go(-1) 区别
    js
    html _ 提取html片段内的纯文本
    vue-x action 的相互调用
    java通过过滤器 设置跨域允许
    git-搭建企业git服务器
  • 原文地址:https://www.cnblogs.com/syzf2222/p/15763707.html
Copyright © 2020-2023  润新知