现在的位置: 首页 > 综合 > 正文

hdu 4366 Successor 线段树

2018年05月02日 ⁄ 综合 ⁄ 共 2134字 ⁄ 字号 评论关闭

题意:

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

题解:

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

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

代码:

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
using namespace std;

const int maxn=5e4+10;
const int maxm=1e6+10;
struct node{
    int num,ability,loyalty;
}f[maxn];
struct tree{
    int l,r,maxv;
}e[maxn*4];
int ha[maxm],l[maxn],r[maxn],t,ans[maxn];
vector<int>mm[maxn];
void dfs(int x)
{
    l[x]=t++;
    for(int i=0;i<mm[x].size();i++)
    {
        dfs(mm[x][i]);
    }
    r[x]=t;
}
int cmp(node a,node b)
{
    if(a.ability==b.ability)return a.num<b.num;
    return a.ability>b.ability;
}
void build(int a,int b,int c)
{
    e[c].l=a;
    e[c].r=b;
    e[c].maxv=-1;
    if(a==b)return ;
    int mid=(a+b)/2;
    build(a,mid,2*c);
    build(mid+1,b,2*c+1);
}
void update(int a,int b,int c,int val)
{
    if(e[c].l==a&&e[c].r==b)
    {
        e[c].maxv=val;
        return ;
    }
    int mid=(e[c].l+e[c].r)/2;
    if(b<=mid)update(a,b,2*c,val);
    else if(a>mid)update(a,b,2*c+1,val);
    e[c].maxv=max(e[2*c].maxv,e[2*c+1].maxv);
}
int query(int a,int b,int c)
{
    if(a>b)return -1;
    if(e[c].l==a&&e[c].r==b)return e[c].maxv;
    int mid=(e[c].l+e[c].r)/2;
    if(b<=mid)return query(a,b,2*c);
    else if(a>mid)return query(a,b,2*c+1);
    else return max(query(a,mid,2*c),query(mid+1,b,2*c+1));
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int i,j,k,n,m,pre;
        scanf("%d%d",&n,&m);
        for(i=0;i<n;i++)mm[i].clear();
        for(i=1;i<n;i++)
        {
            scanf("%d%d%d",&pre,&f[i].loyalty,&f[i].ability);
            mm[pre].push_back(i);
            f[i].num=i;
            ha[f[i].loyalty]=i;
        }
        t=1;
        dfs(0);
        build(1,t-1,1);
        sort(f+1,f+n,cmp);
        /*for(i=1;i<n;i++)
        {
            printf("%d:%d %d% d\n",i,f[i].num,f[i].loyalty,f[i].ability);
            printf("%d %d\n",l[f[i].num],r[f[i].num]);
        }*/
        i=1;
        while(i<n)
        {
            j=i;
            while(j<n&&f[i].ability==f[j].ability)
            {
                k=query(l[f[j].num]+1,r[f[j].num]-1,1);
                if(k==-1)ans[f[j].num]=-1;
                else ans[f[j].num]=ha[k];
                j++;
            }
            j=i;
            while(j<n&&f[i].ability==f[j].ability)
            {
                update(l[f[j].num],l[f[j].num],1,f[j].loyalty);
                j++;
            }
            i=j;
        }
        while(m--)
        {
            scanf("%d",&k);
            printf("%d\n",ans[k]);
        }
    }
    return 0;
}

抱歉!评论已关闭.