题目链接:点击打开链接
思路:
把题目转化一下就是: 求一个区间内所有大于能力值v的人中忠诚度最大的是哪个人。
我们考虑分块, 对于一个块内的人, 我们另开一个数组维护, 将块内的人按照能力值排序, 二分这个能力值, 之后还要维护一个左端点变化的区间最大值, 预处理即可。
细节参见代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <ctime>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const double PI = acos(-1);
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
// & 0x7FFFFFFF
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 50000 + 10;
const int sqr = sqrt(maxn) + 10;
int T,n,m;
int belong[maxn]; /// 每个数属于哪个块
int block; /// 块的大小
int num; /// 块的个数
int r[maxn], l[maxn]; /// 每块的左右边界
struct node {
int l, a, id;
node(int l=0, int a=0, int id=0):l(l), a(a), id(id) {}
bool operator < (const node& rhs) const {
return a < rhs.a;
}
} c[maxn];
vector<node> b[maxn];
int id[maxn], v[maxn], a[maxn], Max[sqr][sqr], p[sqr][sqr];
void build() {
///********************************///
block = sqrt(n);
num = n / block;
if(n % block) num++;
for(int i = 1; i <= num; i++) {
l[i] = (i-1)*block+1;
r[i] = i*block;
}
r[num] = n;
for(int i = 1; i <= n; i++) {
belong[i] = (i-1)/block+1;
}
///********************************///
for(int i = 1; i <= num; i++) {
for(int j = l[i]; j <= r[i]; j++) {
int idd = id[j];
c[j] = node(v[idd], a[idd], idd);
b[i].push_back(node(v[idd], a[idd], idd));
}
sort(b[i].begin(), b[i].end());
int len = b[i].size();
Max[i][len] = -1;
for(int j = len-1; j >= 0; j--) {
if(Max[i][j+1] < b[i][j].l) {
Max[i][j] = b[i][j].l;
p[i][j] = b[i][j].id;
}
else {
Max[i][j] = Max[i][j+1];
p[i][j] = p[i][j+1];
}
}
}
}
int query(int fa, int x, int y) {
int ans = -1, id = -1;
if(belong[x] == belong[y]) {
for(int i = x; i <= y; i++) {
if(a[fa] < c[i].a && ans < c[i].l) {
ans = c[i].l;
id = c[i].id;
}
}
return id;
}
else {
for(int i = x; i <= r[belong[x]]; i++) {
if(a[fa] < c[i].a && ans < c[i].l) {
ans = c[i].l;
id = c[i].id;
}
}
for(int i = belong[x]+1; i < belong[y]; i++) {
int pos = upper_bound(b[i].begin(), b[i].end(), node(0, a[fa], 0)) - b[i].begin();
int cur = Max[i][pos];
if(ans < cur) {
ans = cur;
id = p[i][pos];
}
}
for(int i = l[belong[y]]; i <= y; i++) {
if(a[fa] < c[i].a && ans < c[i].l) {
ans = c[i].l;
id = c[i].id;
}
}
return id;
}
}
int pre[maxn], cnt, last[maxn];
vector<int> g[maxn];
void dfs(int root, int fa) {
pre[root] = ++cnt;
id[cnt] = root;
int len = g[root].size();
for(int i = 0; i < len; i++) {
int v = g[root][i];
if(v != fa) dfs(v, root);
}
last[root] = cnt;
}
void init() {
for(int i = 0; i <= n; i++) {
g[i].clear();
b[i].clear();
}
cnt = 0;
}
int main() {
scanf("%d",&T);
while(T--) {
scanf("%d%d", &n, &m);
init();
for(int i = 1; i < n; i++) {
int fa;
scanf("%d%d%d", &fa, &v[i], &a[i]);
g[fa].push_back(i);
}
dfs(0, 0);
build();
while(m--) {
int op; scanf("%d", &op);
printf("%d\n", query(op, pre[op], last[op]));
}
}
return 0;
}