题意:某公司有n个人,编号从0到n-1,0号是BOSS。除BOSS外,每个人有忠诚度和能力两个属性,每个人的忠诚度都不同。每个人都有可能被BOSS炒鱿鱼,当某个人被炒后,他的所有下级中能力大于他且具有最大忠诚度的人将取代他的位置。现在给定所有人的上下级关系(下级的编号总是比上级小)和一些被炒鱿鱼的人的编号,输出取代被炒人的人的编号,如果没人取代被炒人,输出“-1”。
分析:首先,把以每个节点为根的子树转化为连续区间以便于处理。然后,按能力值由大到小对员工进行排序,能力值相同时,编号小的排在前面。最后,从左到右求以某个人为根的子树中忠诚度最大的人的编号,然后将根的忠诚度插入到线段树中。
注意:C++提交会爆栈。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
const int maxn = 50010;
int t, n, m;
int ans[maxn];
int L[maxn], R[maxn], idx;
bool vis[maxn];
int Max[maxn<<2];
map<int, int> mp;
vector<int> v[maxn];
struct Staff {
int b, c, id;
}s[maxn];
bool cmp(Staff s1, Staff s2)
{
if (s1.c != s2.c) {
return s1.c > s2.c;
} else {
return s1.id < s2.id;
}
}
void build(int l, int r, int rt)
{
Max[rt] = -1;
if (l == r) {
return ;
}
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m + 1, r, rt << 1 | 1);
return ;
}
void update(int l, int r, int rt, int p, int c)
{
if (l == r) {
Max[rt] = c;
return ;
}
int m = (l + r) >> 1;
if (p <= m) {
update(l, m, rt << 1, p, c);
} else {
update(m + 1, r, rt << 1 | 1, p, c);
}
Max[rt] = max(Max[rt<<1], Max[rt<<1|1]);
return ;
}
int query(int l, int r, int rt, int L, int R)
{
if (L <= l && R >= r) {
return Max[rt];
}
int m = (l + r) >> 1;
int ret = -99999;
if (L <= m) {
ret = max(ret, query(l, m, rt << 1, L, R));
}
if (R > m) {
ret = max(ret, query(m + 1, r, rt << 1 | 1, L, R));
}
return ret;
}
void dfs(int x)
{
L[x] = idx;
vis[x] = true;
int size = v[x].size();
for (int i = 0; i < size; ++i) {
if (!vis[v[x][i]]) {
idx++;
dfs(v[x][i]);
}
}
R[x] = idx;
}
int main()
{
scanf("%d", &t);
while (t--) {
for (int i = 0; i < maxn; ++i) {
v[i].clear();
}
mp.clear();
scanf("%d%d", &n, &m);
int a, b, c;
for (int i = 1; i <= n - 1; ++i) {
scanf("%d%d%d", &a, &b, &c);
v[a].push_back(i);
s[i].b = b;
s[i].c = c;
s[i].id = i;
mp[b] = i;
}
mp[-1] = -1;
sort(s + 1, s + n, cmp);
build(1, n - 1, 1);
idx = 0;
memset(vis, false, sizeof(vis));
dfs(0);
for (int i = 1; i <= n - 1; ++i) {
int ret = query(1, n - 1, 1, L[s[i].id], R[s[i].id]);
ans[s[i].id] = mp[ret];
update(1, n - 1, 1, L[s[i].id], s[i].b);
}
int num;
for (int i = 0; i < m; ++i) {
scanf("%d", &num);
printf("%d\n", ans[num]);
}
}
return 0;
}