统计人数(树剖/dp)

109 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情
本文已参与「新人创作礼」活动,一 起开启掘金创作之路。

题目
一家公司里有 nn 个员工,除了公司 CEO 外,每个人都有一个直接上司。我们想知道,每个人的团队(包括他/她自己、他的直接下属和间接下属)一共有多少人?

输入格式

第一行一个整数nn。

接下来一行,n−1n−1个整数f2,f3,…,fnf2,f3,…,fn,fi(1≤fi<i)fi(1≤fi<i)表示第ii个员工的上司。其中11号点为CEO,没有上司。

输出格式

一行n个整数,表示第1∼n1∼n个人的团队人数。

这是一个很经典的树形dp的题目如果我们使用树形dp去写这题的话dp[i]+=dp[j]dp[i] += dp[j] ij的父节点i为j的父节点 这样我们经过on的遍历就可以获得每个人的子树有多少个人

vector<int> v[N];
int a[N];
void dfs(int u) {
    a[u] = 1;
    for(auto x : v[u]) {
        dfs(x);
        a[u] += a[x];
    }
}
void solve()
{
   int n; cin >> n;
   for(int i = 2; i <= n; i++) {
     int x; cin >> x;
     v[x].pb(i);
   }
   dfs(1);
  rep(i,n) cout << a[i] << " \n"[i == n];
}

然后我发现这题可以用树剖去写(虽然有点杀鸡用牛刀了)就是我们将这个树用重子链和轻子链拆分去构成一个线段树然后通过线段树的区间求和去得到这个子树中结点的个数

image.png

image.png

image.png

这只是我一时无聊想起来的写法还是不建议大家赛时这样写(但是如果你有模板的话写的还是挺快的)