题意
给你一棵树,每个数有自己的权值,然后让你求每个节点的儿子节点中有几个节点的权值是比它大的个数。
思路
离散化+树状数组+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;
}