SGU507 Treediff SET+启发式合并

本文介绍了一种针对树形结构的数据处理算法,该算法能够快速计算每个内部节点下所有叶子节点间的最小绝对差值。通过对叶子节点建立集合并采用启发式合并的方式,实现了高效的递归计算。

对于每一个节点查询,他的所有的叶子节点之差最小的值

先对叶子建立set然后向上递归启发式合并,并在合并同时更新值就可以了



507. Treediff
Time limit per test: 0.5 second(s)
Memory limit: 262144 kilobytes
input: standard
output: standard

Andrew has just made a breakthrough in complexity theory: he thinks that he can prove P=NP if he can get a data structure which allows to perform the following operation quickly. Naturally, you should help him complete his brilliant research. Consider a rooted tree with integers written in the leaves. For each internal (non-leaf) node v of the tree you must compute the minimum absolute difference between all pairs of numbers written in the leaves of the subtree rooted at v
Input
The first line of the input file contains two integers n and m — overall number of nodes in the tree and number of leaves in the tree respectively. . All nodes are numbered from 1 ton. Node number 1 is always the root of the tree. Each of the other nodes has a unique parent in the tree. Each of the next n - 1 lines of the input file contains one integer — the number of the parent node for nodes 2, 3,..., n respectively. Each of the last m lines of the input file contains one integer ranging from  to  — the value of the corresponding leaf. Leaves of the tree have numbers from n -m + 1 to n
Output
Output one line with n - m integers: for each internal node of the tree output the minimum absolute difference between pairs of values written in the leaves of its subtree. If there is only one leaf in the subtree of some internal node, output number 231 - 1 for that node. Output the answers for the nodes in order from node number 1 to n - m
Example(s)
sample input
sample output
5 4
1
1
1
1
1 
4 
7 
9
2

sample input
sample output
5 4
1
1
1
1
1 
4 
7 
10
3

sample input
sample output
7 4
1
2
1
2
3
3
2 
10 
7 
15
3 3 8

sample input
sample output
2 1
1
100
2147483647 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>
#include<iterator>
#include<vector>

using namespace std;

#define INF 2147483647
#define pb push_back
#define MAXN 50100

vector<int> g[MAXN];
set<int> s[MAXN];
set<int>::iterator si,pre,suc;
int v[MAXN];
int n,m;

int merge(set<int> &x,set<int> &y)
{
    if(x.size()<y.size()) swap(x,y);
    int tmp=INF;
    for(si=y.begin();si!=y.end();si++)
    {
        pre=suc=x.lower_bound(*si);
        if(pre!=x.begin()) pre--;
        if(pre!=x.end()) tmp=min(tmp,abs(*si-*pre));
        if(suc!=x.end()) tmp=min(tmp,abs(*si-*suc));
        x.insert(*si);
    }
    return tmp;
}

void dfs(int u)
{
    if(!g[u].size())
    {
        s[u].insert(v[u]);
        v[u]=INF;
        return;
    }
    v[u]=INF;
    for(int i=0;i<g[u].size();i++)
    {
        int vv=g[u][i];
        dfs(vv);
        v[u]=min(v[u],v[vv]);
        v[u]=min(v[u],merge(s[u],s[vv]));
    }
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
            g[i].clear();
            s[i].clear();
        }
        for(int i=2;i<=n;i++)
        {
            int f;
            scanf("%d",&f);
            g[f].pb(i);
        }
        for(int i=n-m+1;i<=n;i++) scanf("%d",&v[i]);
        dfs(1);
        printf("%d",v[1]);
        for(int i=2;i<=n-m;i++)
            printf(" %d",v[i]);
        printf("\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值