题意:
现在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;
}