HDU 4366

線段樹    

題意: 每個員工有一個上級,每個上級有很多下級,求fire掉一個人之後可以用哪個人頂上


/*
線段樹    
題意: 每個員工有一個上級,每個上級有很多下級,求fire掉一個人之後可以用哪個人頂上
替換規則:該員工的能力比他高的下級中, loyalty最大的那個,如果沒有,則輸出 -1


思路:員工的上下級關係應該是一棵樹,dfs,dfs次序對應轉化爲一維之後的下標{[()]},就像這樣;
      一棵子樹的結點對應成線段上的點總是連續的,我們記錄開始結點ll,跟結束結點rr;    
      那麼求該子樹根節點用哪個替換就轉化成求[ll,rr]區間上,ability比根節點大的中loyalty最大的;
      
      將結點按ability按從大到小排序,然後一個個依次加入線段樹中,這樣就能保證在當前結點加入前,線段樹
      中結點的ability都是比它大的,先求該節點的[ll,rr]區間內loyalty最大的,然後加入該節點
      線段樹要維護的就是最大的loyalty,又因loyalty是唯一的,所以可以對應員工編號

*/

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdlib>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 50005
#include<map>
using namespace std;
int Max[N<<2],ans[N],head[N],ll[N],rr[N],p[N];
int cnt;
map<int,int > mp;
struct person{
    int l,a,no;
}num[N];
struct edge{
    int v,next;
}e[N];
bool cmp(const person x,person y){
    if(x.a!=y.a)
    return x.a>y.a;
    return x.no<y.no;
}
void init(){
    cnt=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v){
    e[cnt].v=v;e[cnt].next=head[u];head[u]=cnt++;
}
void dfs(int x){
    p[x]=cnt;
    ll[x]=cnt;
    for(int i=head[x];i!=-1;i=e[i].next){
        cnt++;
        dfs(e[i].v);
    }
    rr[x]=cnt;


}
void pushup(int rt){
    Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}
void build(int l,int r,int rt){
    Max[rt]=0;
    if(l==r){
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
int query(int L,int R,int l,int r,int rt){
    if(L<=l&&r<=R){
        return Max[rt];
    }
    int m=(l+r)>>1;
    if(R<=m)
    return query(L,R,lson);
    if(L>m)
    return query(L,R,rson);
    return max(query(L,R,lson),query(L,R,rson));
}
void update(int x,int i,int l,int r,int rt){
  //  cout<<p[x]<<' '<<i<<' '<<l<<' '<<r<<' '<<rt<<endl;
    if(l==r){
        Max[rt]=num[i].l;
        return ;
    }
    int m=(l+r)>>1;
    if(p[x]<=m)
    update(x,i,lson);
    else
    update(x,i,rson);
    pushup(rt);
}
int main()
{
    int T,n,m,j,x;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        init();
        for(int i=2;i<=n;i++){
            scanf("%d",&j);
            num[i].no=i;
            scanf("%d%d",&num[i].l,&num[i].a);
            mp[num[i].l] = i;
            addedge(j+1,i);
        }
        cnt=1;
        dfs(1);
        build(1,n,1);
        sort(num+2,num+1+n,cmp);
        for(int i=2;i<=n;i++){
            ans[num[i].no]=query(ll[num[i].no],rr[num[i].no],1,n,1);
            if(ans[num[i].no]!=0){
                ans[num[i].no]=mp[ans[num[i].no]];
            }
            update(num[i].no,i,1,n,1);
        }
        while(m--){
            scanf("%d",&x);
            printf("%d\n",ans[x+1]-1);

        }
    }
    return 0;
}


發佈了104 篇原創文章 · 獲贊 3 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章