HDU 4366 Successor(dfn序 + 线段树)

来源:互联网 发布:知鸟软件 编辑:程序博客网 时间:2024/05/21 21:03

http://acm.hdu.edu.cn/showproblem.php?pid=4366

Problem Description
Sean owns a company and he is the BOSS.The other Staff has one Superior.every staff has a loyalty and ability.Some times Sean will fire one staff.Then one of the fired man’s Subordinates will replace him whose ability is higher than him and has the highest loyalty for company.Sean want to know who will replace the fired man.

Input
In the first line a number T indicate the number of test cases. Then for each case the first line contain 2 numbers n,m (2<=n,m<=50000),indicate the company has n person include Sean ,m is the times of Sean’s query.Staffs are numbered from 1 to n-1,Sean’s number is 0.Follow n-1 lines,the i-th(1<=i<=n-1) line contains 3 integers a,b,c(0<=a<=n-1,0<=b,c<=1000000),indicate the i-th staff’s superior Serial number,i-th staff’s loyalty and ability.Every staff ‘s Serial number is bigger than his superior,Each staff has different loyalty.then follows m lines of queries.Each line only a number indicate the Serial number of whom should be fired.

Output
For every query print a number:the Serial number of whom would replace the losing job man,If there has no one to replace him,print -1.

Sample Input

1
3 2
0 100 99
1 101 100
1
2

Sample Output

2
-1


题意:

现在n个人,其中编号0的是老板,之后n-1个员工,每个员工只有一个上司,有一个忠诚值和能力值。每次要解雇一个人的时候,从他的下属中选取能力值大于他的且忠诚值最高的一个,若不存在则输出-1.共m次询问,每次询问i,输出解雇i会选择哪个编号的员工代替值。(所有询问都不相互影响)

题解:

以n个人的关系,我们可以建一棵树。之后我们用dfs将树转换成一维数组,使得每个人的下属都在连续的一段当中,方便用线段树维护。

之后将n-1个员工以能力值排序,能力值高的先插入到线段树中,然后确定能力值低的人的下属中在线段树存在,存在则返回最大的忠诚值。由于每个人的忠诚值都不相同,所以可以用哈希数组保存每个忠诚值对应的员工编号,从而预处理出所有员工的询问结果。只有的询问就能在O(1)时间内得到结果了。

1.涉及到类似子区间找点问题,学会将树转换成线性区间
2.合理利用线段树来更新和查找 ,这种插入的方法很重要


#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <map>#include <vector>using namespace std;#define lson l,mid,i<<1#define rson mid+1,r,i<<1|1const int N = 5 * 1e5 + 100;map<int,int>mm;vector<int> vet[N];pair<int,int> pll[N];int ans[N],dep,in[N],out[N],tr[N*4],res;struct Q{    int x,id,a;    Q(){}    Q(int x,int id,int a):x(x),id(id),a(a){}    friend bool operator <  (const Q a,const Q b)    {        return a.a > b.a;    }}Que[N];void dfs(int u){    ++dep;    in[u] = dep;    for(int i=0; i<vet[u].size(); i++)    {        int v = vet[u][i];        dfs(v);    }    out[u] = dep;}void built(int l,int r,int i){    tr[i] = -1;    if(l==r) return;    int mid = (l+r) >> 1;    built(lson);    built(rson);}void update(int l,int r,int i,int id ,int x){    if(l==r && l==id)    {        tr[i] = x;        return;    }    if(l>=r) return;    int mid = (l+r)>>1;    if(mid>=id) update(lson,id,x);    else update(rson,id,x);    tr[i] = max(tr[i<<1],tr[i<<1|1]);}void query(int l,int r,int i,int a,int b){    if( l>=a && r<=b)    {        res = max(res ,tr[i]);        return;    }    if(l>=r) return;    int mid = (l+r)>>1;    if(mid>=a) query(lson,a,b);    if(mid<b) query(rson,a,b);    return;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n,m;        scanf("%d%d",&n,&m);        for(int i=0;i<n;i++) vet[i].clear();        mm.clear();        mm[-1] = -1;        pll[0] = make_pair(-1,-1);        for(int i=1;i<n;i++)        {            int u,a,b;            scanf("%d %d %d",&u,&a,&b);             vet[u].push_back(i);            pll[i] = make_pair(b,a);             mm[a] = i;        }        for(int i=1;i<=m;i++)        {            int x;            scanf("%d",&x);            Que[i] = Q(x,i,pll[x].first);        }        dep = 0;        dfs(0);        sort(Que+1,Que+1+m);        sort(pll,pll+n);        built(1,n,1);        int pos = n-1;        for(int i=1;i<=m;i++)        {            while(pos>0 && pll[pos].first > Que[i].a) update(1,n,1,mm[pll[pos].second]+1,pll[pos].second),pos--;            res =  -1;            query(1,n,1,in[Que[i].x],out[Que[i].x]);            ans[Que[i].id] = mm[res];        }        for(int i=1;i<=m;i++) printf("%d\n",ans[i]);    }    return 0;}
0 0
原创粉丝点击