P3605 [USACO17JAN]Promotion Counting P

该博客介绍了一种利用离散化、树状数组和深度优先搜索(DFS)解决USACO竞赛中关于树形结构和权值比较问题的方法。通过离散化节点,构建图,然后用DFS遍历每个节点,利用树状数组快速找到大于当前节点权值的儿子节点数量,从而得出每个节点满足条件的儿子节点个数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

给你一棵树,每个数有自己的权值,然后让你求每个节点的儿子节点中有几个节点的权值是比它大的个数。

思路

离散化+树状数组+dfs
1.离散化:

for (int i = 1; i <= n; i ++) { cin >> a[i]; b[i] = a[i]; }

sort(b + 1, b + 1 + n);
for (int i = 1; i <= n; i ++) a[i] = lower_bound(b + 1, b + 1 + n, a[i]) - b;

2.存图

for (int i = 2; i <= n; i ++)
{
	int x; cin >> x;
	vec[x].push_back(i);
}

3.寻找值(dfs):
因为每一个节点可能会有多个儿子,所以我们用dfs把所有的儿子都遍历一遍。对于一个节点我们怎样寻找它满足条件的儿子节点呢?因为我们每次都是遍历完了它所有的儿子节点,然后再来寻找的,这里我们用树状数组,值大的会在当前节点的后面,所以,开始的时候我们要找到当前节点所拥有的比它大的节点,在遍历完了之后,我们在来算满足条件的点,然后两个值相减,就得到了它现在拥有的点。

void dfs(int x)
{
    ans[x] = -(sum(n) - sum(a[x]));
    for (auto t : vec[x]) dfs(t);
    ans[x] += sum(n) - sum(a[x]);
    add(a[x], 1);
}

AC代码:

#include <bits/stdc++.h>

#define int long long

using namespace std;

const int N = 1e5 + 10;

int n;
int tr[N];
int a[N], b[N], ans[N];
vector<int> vec[N];

int lowbit(int x) { return x & -x; }

void add(int x, int k) { for (int i = x; i <= n; i += lowbit(i)) tr[i] += k; }

int sum(int x)
{
    int sum = 0;
    for (int i = x; i; i -= lowbit(i)) sum += tr[i];
    return sum;
}

void dfs(int x)
{
    ans[x] = -(sum(n) - sum(a[x]));
    for (auto t : vec[x]) dfs(t);
    ans[x] += sum(n) - sum(a[x]);
    add(a[x], 1);
}

signed main()
{
    std::ios::sync_with_stdio(false);

    cin >> n;
    for (int i = 1; i <= n; i ++) { cin >> a[i]; b[i] = a[i]; }

    sort(b + 1, b + 1 + n);
    for (int i = 1; i <= n; i ++) a[i] = lower_bound(b + 1, b + 1 + n, a[i]) - b;

    for (int i = 2; i <= n; i ++)
    {
        int x; cin >> x;
        vec[x].push_back(i);
    }

    dfs(1);

    for (int i = 1; i <= n; i ++) cout << ans[i] << endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值