zoukankan      html  css  js  c++  java
  • Successor HDU

    Successor

    HDU - 4366

    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.
    第一行一个整数,表示测试数据组数。
    对于每组数据,第一行两个整数n和m,表示公司的员工和询问次数。
    接下来n-1行,第i行,3个整数,i的上级,忠诚度,能力值。老总的编号为0,所有员工的忠诚度都不一样。
    接下来m行,每行一个整数,表示要开除某个人,你需要输出替代他的员工编号。如果不存在,输出-1.

    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.
    对于每个要开除的人,你需要输出替代他的员工编号。如果不存在,输出-1.

    Sample Input

    1
    3 2
    0 100 99
    1 101 100
    1
    2
    

    Sample Output

    2
    -1
    

    题意:

    公司里自上而下是一个树形结构。

    每个员工都有一个忠诚度和能力值。如果把一个员工开除,需要在他的下属中,找到一个能力值比他高,且忠诚度最大的员工来替代他。

    m个询问,每行一个整数,表示要开除某个人,你需要输出替代他的员工编号。如果不存在,输出-1.

    思路:

    一棵树的子树中,dfs序是连续的。

    所以我们先通过dfs来把树形问题转为区间问题。

    又因为所有员工的忠诚度都不一样。 所以我们可以用一个map把员工的编号和忠诚度对应起来。

    我们先以员工的能力值为指标,降序排序。

    然后预处理出所有答案,输入直接O(1) 输出结果。

    如何预处理出所有员工节点的答案呢?

    我们知道推论①:一个员工对他的领导的答案值有影响,当且仅当这个员工的能力值大于他的那个领导的答案值。

    那么我们可以在排序后,

    在线段树中从大到小依次加入员工,

    这样的话我们对一个员工,询问线段树中这个员工的dfs序的时间戳区间中的忠诚度的最大值。(区间查询)

    中横渡对应下编号就是这个员工的答案。

    然后把这位员工的忠诚度加入到员工的dfs序的时间戳位置中。(单点更新)

    为什么这样对?

    因为对上面讲到的推论①,对其可能有影响的员工已经全部加入到线段树中了。

    他只需要询问在自己的下属员工中(在时间戳区间中)的忠诚度最大值即可。

    细节见代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #define ALL(x) (x).begin(), (x).end()
    #define sz(a) int(a.size())
    #define all(a) a.begin(), a.end()
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    // #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
    using namespace std;
    typedef long long ll;
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
    ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2) { ans = ans * a % MOD; } a = a * a % MOD; b /= 2;} return ans;}
    inline void getInt(int *p);
    const int maxn = 50010;
    const int inf = 0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    int T;
    map<int, int> mp;
    std::vector<int> son[maxn];
    int tree[maxn << 2];
    int ans[maxn];
    int n, m;
    int tot;
    void init()
    {
        repd(i, 1, n * 4) {
            tree[i] = -1;
        }
        tot = 0;
        mp.clear();
        repd(i, 0, n) {
            son[i].clear();
            ans[i] = -1;
        }
        mp[-1] = -1;
    }
    struct node {
        int ab;
        int lo;
        int id;
        int timel;
        int timer;
        bool operator <(const node &bb )const
        {
            if (ab != bb.ab) {
                return ab > bb.ab;
            } else {
                return timel < bb.timel;
            }
        }
    } data[maxn];
    void dfs(int x)
    {
        data[x].timel = ++tot;
        for (auto y : son[x]) {
            dfs(y);
        }
        data[x].timer = tot;
    }
    int ask(int rt, int l, int r, int ql, int qr)
    {
        if (ql <= l && r <= qr) {
            return tree[rt];
        }
        int res = -1;
        int mid = (l + r) >> 1;
        if (ql <= mid) {
            res = max(res, ask(rt << 1, l, mid, ql, qr));
        }
        if (qr > mid) {
            res = max(res, ask(rt << 1 | 1, mid + 1, r, ql, qr));
        }
        return res;
    }
    void update(int rt, int l, int r, int pos, int val)
    {
        if (l == r && l == pos) {
            tree[rt] = val;
            return;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid) {
            update(rt << 1, l, mid, pos, val);
        }
        if (pos > mid) {
            update(rt << 1 | 1, mid + 1, r, pos, val);
        }
        tree[rt] = max(tree[rt << 1], tree[rt << 1 | 1]);
    
    }
    
    int main()
    {
        //freopen("D:\code\text\input.txt","r",stdin);
        //freopen("D:\code\text\output.txt","w",stdout);
        scanf("%d", &T);
        while (T--) {
            scanf("%d %d", &n, &m);
            init();
            int x;
            repd(i, 1, n - 1) {
                scanf("%d %d %d", &x, &data[i].lo, &data[i].ab);
                data[i].id = i;
                mp[data[i].lo] = i;
                son[x].push_back(i);
            }
            dfs(0);
            sort(data + 1, data + n);
            for (int i = 1; i < n; ++i) {
                ans[data[i].id] = mp[ask(1, 1, tot, data[i].timel, data[i].timer)];
                update(1, 1, tot, data[i].timel, data[i].lo);
            }
            while (m--) {
                int x;
                scanf("%d", &x);
                printf("%d
    ", ans[x] );
            }
    
        }
        return 0;
    }
    
    inline void getInt(int *p)
    {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        } else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }
    
    
    
    
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    sql server 2008 64位连接sql 2000服务器的时候出现
    MySQL忘记密码怎么修改密码
    vs2015 行数统计
    javascript和c#aes加密方法互解
    vs2015 不能启动 iis express
    修改oracle的字符集操作方法
    PL/SQL Developer连接本地Oracle 11g 64位数据库
    CodeSmith Generator 7.0.2激活步骤
    PetaPoco利用ODP.NET Managed Driver连接Oracle
    解决Chrome插件安装时出现的“程序包无效”问题亲测可用
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/11494752.html
Copyright © 2011-2022 走看看