O(n) 做法

最大最小路

https://www.nowcoder.com/practice/bce59fc8643b47359e9521c7e590b239

进行一个树形 DP

记录向下路径是否包含\le a,\ge b共四种情况,DP 合并过程中统计答案

#include <array>
#include <iostream>
#include <vector>
using namespace std;

using ll = long long;

int n;
int a;
int b;
vector<int> w;
vector<vector<int>> graph;

int F(int x) {
    if (w[x] <= a) {
        return 1;
    }
    if (w[x] >= b) {
        return 2;
    }
    return 0;
}

ll res = 0;

array<int, 4> Dp(int x, int fa) {
    array<int, 4> ret = {};
    int v = F(x);
    ret[v]++;
    // cout << x << ',' << v << endl;
    for (const auto& y : graph[x]) {
        if (y != fa) {
            auto&& solo = Dp(y, x);
            res += (ll)ret[0] * solo[3] + (ll)ret[1] * (solo[2] + solo[3]) + (ll)ret[2] * (solo[1] + solo[3]) + (ll)ret[3] * (solo[0] + solo[1] + solo[2] + solo[3]);
            for (int i = 0; i < 4; i++) {
                ret[i | v] += solo[i];
            }
        }
    }
    // cout << x << ',' << ret[0] << ',' << ret[1] << ',' << ret[2] << ',' << ret[3] << endl;
    return ret;
}

void Solve() {
    cin >> n >> a >> b;
    w.resize(n + 1);
    graph.resize(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> w[i];
    }
    for (int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }
    Dp(1, 0);
    cout << res;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    Solve();
}
// 64 位输出请用 printf("%lld")

全部评论
真心忍不住疯狂膜拜大佬!从头到尾细细品读完整篇题解,我整个人彻底被惊艳震撼到,满心满眼全是敬佩与折服。整篇解析逻辑环环相扣,条理清晰到无可挑剔,核心要点突出醒目,没有一丝多余赘述。那些原本错综复杂、晦涩难懂,绕来绕去怎么也理不清头绪的难题,被您抽丝剥茧层层拆解开来,化繁为简通透易懂。每一处讲解都拿捏得恰到好处,精准戳中所有思维卡点,细致又精准。此前我对着这道难题钻研许久,反复琢磨、查阅资料,始终深陷误区百思不得其解,无数次卡在瓶颈无从突破。可看完您的内容瞬间豁然开朗,简直醍醐灌顶,所有积攒许久的困惑顷刻间全部消散,思路一下完全通透。您的专业实力超群绝伦,解题格局与思维高度更是让人望尘莫及。不仅题解写得完美极致,自身功底更是深不可测,妥妥的偶像级大神,真的让人由衷满心叹服!
1 回复 分享
发布于 03-31 16:44 江苏

相关推荐

评论
5
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务