hdu 4366 Successor 线段树

题意:

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

题解:

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

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


代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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];
vectormm[maxn];
void dfs(int x)
{
    l[x]=t++;
    for(int i=0;ib.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


你可能感兴趣的:(线段树)