HDU 4366 Successor(DFS序+线段树)

版权声明:没人会转的( ̄▽ ̄) https://blog.csdn.net/j2_o2/article/details/86537291
题目链接
题意

公司里的每个员工都有一个忠诚度和能力值。
如果把一个员工开除,需要在他的下属中,找到一个能力值比他高,且忠诚度最大的员工来替代他。
第一行一个整数,表示测试数据组数。
对于每组数据,第一行两个整数n和m,表示公司的员工数和查询数。
接下来n-1行,第i行,3个整数,i的上级,忠诚度,能力值。老总的编号为0,所有员工的忠诚度都不一样。
接下来m行查询,每行一个整数,表示要开除某个人,输出替代他的员工编号。如果无法替代,输出-1.

思路

用DFS序转为线性存储,每个人的下级在俩时间戳内。
将每个人按能力值排序。用线段树维护单点修改,区间查询的忠诚度最大值。
按能力从大到小,每次先查询此人的时间戳内忠诚度最大值,如果不存在即-1,存在即表示可被替代,然后单点修改。
由于每个人忠诚度不一样,可以用map来维护忠诚度与人的编号关系。

有个问题,如果俩人能力值相同,如果先更新儿子节点,那么查询会查到父亲的值。
所以要先更新父亲节点,排序时使能力值相同的人时间戳小的排前面即可。

代码
#include<bits/stdc++.h>
using namespace std;

#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r

vector<int> e[50005];
map<int, int> mp;
int tot, ma[200005], ans[50005];
struct Node
{
    int lo, ab, l, r;
}data[50005];

bool cmp(Node a, Node b)
{
    if(a.ab != b.ab) return a.ab > b.ab;
    return a.l < b.l;
}

void init(int n)
{
    tot = 0;
    mp.clear();
    mp[-1] = -1;
    for(int i = 0; i <= n; ++i) e[i].clear();
    memset(ma,-1,sizeof(ma));
}

void dfs(int u)
{
    data[u].l = ++tot;
    for(auto v : e[u]) dfs(v);
    data[u].r = tot;
}

void updata(int rt, int l, int r, int ql, int lo)
{
    if(l == r)
    {
        ma[rt] = lo;
        return;
    }
    int mid = (l+r)>>1;
    if(ql <= mid) updata(lson,ql,lo);
    else updata(rson,ql,lo);
    ma[rt] = max(ma[rt<<1], ma[rt<<1|1]);
}

int query(int rt, int l, int r, int ql, int qr)
{
    if(ql <= l && r <= qr) return ma[rt];
    int mid = (l+r)>>1, tmp = -1;
    if(ql <= mid) tmp = max(tmp, query(lson,ql,qr));
    if(mid < qr) tmp = max(tmp, query(rson,ql,qr));
    return tmp;
}

int main()
{
    int t;
    for(scanf("%d",&t); t; --t)
    {
        int n, m, u;
        scanf("%d%d",&n,&m);
        init(n);
        for(int i = 1; i < n; ++i)
        {
            scanf("%d%d%d",&u,&data[i].lo,&data[i].ab);
            mp[data[i].lo] = i;
            e[u].push_back(i);
        }
        dfs(0);
        sort(data+1,data+n,cmp);
        for(int i = 1; i < n; ++i)
        {
            ans[mp[data[i].lo]] = mp[query(1,1,tot,data[i].l,data[i].r)];
            updata(1,1,tot,data[i].l,data[i].lo);
        }
        for(; m--; printf("%d\n",ans[u])) scanf("%d",&u);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/j2_o2/article/details/86537291