CF1436D

我们来看一下此题:

看到最大值最小,很容易想到二分答案,设二分的值为 x

再设 sumii 的子树中 aj 的和,li 表示 i 的子树中叶子结点的个数,

那么我们假设在点 u 上,且 u 的子树除了 u 以外全部分配完成,那么 u 上的人肯定会优先去人比较少的叶子节点,

那么如果目前合法,u 不合法当且仅当 x<sumulu

时间复杂度:O(nlogn)

其实可以不用二分,直接取 sumulu 的最大值即可

时间复杂度:O(n)


#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
#define int long long // 别忘开 long long

const int maxn = 2e5 + 10;
struct node {
    int to, nxt;
} edge[maxn << 1];
int cnt, head[maxn];
int ans = 0, a[maxn], l[maxn], sum[maxn];

void add (int u, int v) { // 建边
    cnt ++;
    edge[cnt].to = v;
    edge[cnt].nxt = head[u];
    head[u] = cnt;
}

void dfs (int u, int f) {
    sum[u] = a[u];
    int son = 0;
    for (int i = head[u]; i; i = edge[i].nxt) {
        int v = edge[i].to;
        if (v == f) continue;
        dfs (v, u);
        son ++;
        l[u] += l[v]; sum[u] += sum[v];
    }
    if (son == 0) l[u] = 1;
    int res = sum[u] / l[u];
    if (res * l[u] < sum[u]) res ++; 
    ans = max (ans, res); // 取最大值
}

signed main() {
    int n; scanf ("%lld", &n);
    for (int i = 2; i <= n; ++i) {
        int x; scanf ("%lld", &x);
        add (x, i); add (i, x);
    }
    for (int i = 1; i <= n; ++i) scanf ("%lld", &a[i]);
    dfs (1, 0);
    printf ("%lld", ans);
    return 0;
}
posted @   wangzhongyuan  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示