牛客小白月赛29 种树 题解(思维)

题目链接

题目大意

给你一个二叉树,节点要么没有儿子,要么有两个儿子

你每次可以删除两个父亲相同的叶子节点,直到最后剩下一个根节点

显然要删除m=(n-1)/2次

有两种删除方法

第一种:val(x)=max(val(左儿子),val(右儿子) )

第二种:val(x)=min(val(左儿子),val(右儿子) )

最多进行(m+1)/2次第一种操作,要你求根节点的最大值

题目思路

只要根节点的depth[i]<=(m+1)/2,即可以变成根节点的权值

代码

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#define fi first
#define se second
#define debug printf(" I am here
");
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=5e5+5,inf=0x3f3f3f3f,mod=2017;
const double eps=1e-10;
int n,dep[maxn],a[maxn];
int head[maxn],cnt;
bool ye[maxn];
struct edge{
    int to,next;
}e[maxn];
void add(int u,int v){
    e[++cnt]={v,head[u]};
    head[u]=cnt;
}
void dfs(int son,int fa){
    for(int i=head[son];i;i=e[i].next){
        dep[e[i].to]=dep[son]+1;
        dfs(e[i].to,son);
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1,x,y;i<=n;i++){
        scanf("%d%d",&x,&y);
        if(x==0||y==0){
            ye[i]=1;
        }else{
            add(i,x),add(i,y);
        }
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    int del=((n-1)/2+1)/2;
    dfs(1,1);
    int ans=0;
    for(int i=1;i<=n;i++){
        if(!ye[i]) continue;
        if(dep[i]<=del){
            ans=max(ans,a[i]);
        }
    }
    printf("%d
",ans);
    return 0;
}

卷也卷不过,躺又躺不平
原文地址:https://www.cnblogs.com/hunxuewangzi/p/13974856.html