题解 | 小红的树

小红的树

https://www.nowcoder.com/practice/66ab364d3fba487eb39bd3460fd484c0

解题思路

  1. 核心思想:

    • 使用DFS预处理每个节点的子树中红色节点数量
    • 对于每次查询直接返回预处理的结果
  2. 实现步骤:

    • 根据父节点数组构建树(邻接表)
    • DFS遍历树,统计每个节点子树中的红色节点数
    • 处理查询

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 100010;
vector<int> g[N];  // 邻接表
int count_red[N];  // 每个节点子树中的红色节点数
string colors;     // 节点颜色

int dfs(int u) {
    int total = (colors[u-1] == 'R');  // 当前节点是否为红色
    for(int v : g[u]) {
        total += dfs(v);
    }
    return count_red[u] = total;
}

int main() {
    int n;
    cin >> n;
    
    // 读入父节点数组并建图
    for(int i = 2; i <= n; i++) {
        int p;
        cin >> p;
        g[p].push_back(i);
    }
    
    // 读入颜色
    cin >> colors;
    
    // 预处理每个节点的子树红色节点数
    dfs(1);
    
    // 处理查询
    int q;
    cin >> q;
    while(q--) {
        int x;
        cin >> x;
        cout << count_red[x] << endl;
    }
    
    return 0;
}
import java.util.*;

public class Main {
    static int N = 100010;
    static ArrayList<Integer>[] g;
    static int[] count;
    static String colors;
    
    static int dfs(int u) {
        int total = (colors.charAt(u-1) == 'R' ? 1 : 0);  // 当前节点是否为红色
        for(int v : g[u]) {
            total += dfs(v);
        }
        return count[u] = total;
    }
    
    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        
        // 初始化
        g = new ArrayList[N];
        for(int i = 0; i < N; i++) {
            g[i] = new ArrayList<>();
        }
        count = new int[N];
        
        // 读入父节点数组并建图
        for(int i = 2; i <= n; i++) {
            int p = sc.nextInt();
            g[p].add(i);
        }
        
        // 读入颜色
        colors = sc.next();
        
        // 预处理每个节点的子树红色节点数
        dfs(1);
        
        // 处理查询
        int q = sc.nextInt();
        while(q-- > 0) {
            int x = sc.nextInt();
            System.out.println(count[x]);
        }
        
        sc.close();
    }
}

import sys
sys.setrecursionlimit(100010)

def dfs(u, g, color, count):
    """统计以u为根的子树中红色节点数"""
    total = 1 if color[u-1] == 'R' else 0  # 修正:索引从0开始
    for v in g[u]:
        total += dfs(v, g, color, count)
    count[u] = total
    return total

def main():
    # 输入
    n = int(input())
    parents = [1] + list(map(int, input().split()))  # 父节点数组
    colors = input()  # 节点颜色
    
    # 建图(子节点表示)
    g = [[] for _ in range(n + 1)]
    for i in range(2, n + 1):
        g[parents[i-1]].append(i)
    
    # 预处理每个节点的子树红色节点数
    count = [0] * (n + 1)
    dfs(1, g, colors, count)
    
    # 处理查询
    q = int(input())
    for _ in range(q):
        x = int(input())
        print(count[x])

if __name__ == "__main__":
    main()

算法及复杂度

  • 算法:DFS预处理 + 在线查询
  • 时间复杂度:
    • 预处理:
    • 每次查询:
    • 总复杂度:
  • 空间复杂度:,用于存储图和计数数组
全部评论

相关推荐

04-16 10:27
已编辑
美团_Saas_后端开发
今天周一休息,突发奇想写一篇阶段总结。如题,我已经去了一个和Java彻底毫无关联的行业。曾经我以为自己能在计算机行业发光发热,拿到美团offer那会感觉自己天都亮了。没想到刚入行一年多就当了逃兵。从最开始的热爱到现在一看到代码就厌恶,不知道自己经历了什么。所以我去干什么了?答案是:在成都当了租房销售。上班那会压力大了就念叨着去干租房中介,但是一直下不去这个决心,想着自己学了四年多的计算机知识,终究还是不甘心。终于在某一天准备八股文的时候,看着无数篇和工作内容关系不大的理论知识,那一刻下定决心,决定尝试一下销售行业,也算是给自己一个交代。后面阴差阳错的投了成都自如去当租房管家,没想到面试很顺利,在当天一百多个面试的人里面,我成为了为数不多通过的几个幸运儿之一。目前已经培训通过,正式入职,也开了单,有压力但是每天过得很开心,真心喜欢那种和人交流的感觉,哪怕是最后没有选择找我租房。说这些也是想告诉那些大三,大四正在找Java实习而焦虑的同学:你们现在还年轻,选择很多,容错率也很高,可以尽情去尝试自己喜欢的行业和工作。不用因为某一次的面试没通过或者简历石沉大海而焦虑,更不用因为身边人都在挤编程的独木桥就强迫自己跟风。也算是自己的碎碎念吧,也希望自己能在新的领域取得一点小成就。也祝牛油工作顺利!
沉淀小子:干啥都不丢人啊,生存是必须要的,销售很考验一个人综合素质能力的,好的销售人脉和资源可不比写字楼的白领差啊
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

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