列表

详情


NC231598. 神奇的炸鸡国

描述



lzc,gjh和cwy一边吃着炸鸡,一边旅行。这一天他们来到了一个神奇的国度——炸鸡国。

炸鸡国一共有n个人,这里个个都是人才,人人都会炸鸡,可以用a_i来描述第i个人的炸鸡水平。炸鸡国的统治结构是一颗树,通过n-1条边连通。当确定了国王(即确定了树的根)时,可以得到一颗确定的有根树。

f(u)u的子树中炸鸡水平大于等于a_u的总人数(不包含u本身)。

g(u)为以u为根时,的值。

请你输出g(1),g(2),g(3),...,g(n)

输入描述

第一行包含一个正整数,表示炸鸡国的人数。

第二行包含n个正整数,第i个数为,表示第i个人的炸鸡水平。

接下来n-1行每行包含两个正整数uv,表示uv之间有一条边,保证无重边。

输出描述

输出一行,包含n个整数,第i个整数表示g(i)

示例1

输入:

3
6 7 8
1 2
1 3

输出:

2 2 1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 692ms, 内存消耗: 93048K, 提交时间: 2021-12-08 14:00:59

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int s[N];
void add(int x)
{
    while (x<N-1){
        s[x]++;
        x+=x&(-x);
    }
}
int query(int x)
{
    int res=0;
    while (x){
        res+=s[x];
        x-=x&(-x);
    }
    return res;
}
long long f[N],a[N],g[N],dp[N],c[N];
vector<int> e[N];
void dfs(int u,int p)
{
    int res=0;
    for (auto it:e[u]){
        if(it==p) continue;
        int t=query(N-1)-query(a[u]-1);
        dfs(it,u);
        dp[it]=query(N-1)-query(a[u]-1)-t;
        f[u]+=dp[it];
        g[u]+=g[it];
    }
    g[u]+=f[u];
    add(a[u]);
}
void dfs2(int u,int p)
{
    for (auto it:e[u]){
        if(it==p) continue;
        g[it]=g[u]-dp[it]-f[it]+c[a[it]]-1;
        
        dfs2(it,u);
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin>>n;
    for (int i=1;i<=n;i++) cin>>a[i];
    for (int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    dfs(1,0);
    
    for (int i=1;i<=n;i++){
        c[a[i]]=query(N-1)-query(a[i]-1);
    }
    dfs2(1,0);
    for (int i=1;i<=n;i++) cout<<g[i]<<" ";
    return 0;
}

上一题