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