G. Unusual Entertainment
题意:给定一颗以1为根的树,和一个序列
p
p
p,进行多次询问
一次询问给定三个数
l
,
r
,
x
l,r,x
l,r,x,询问
p
[
l
]
.
.
.
p
[
r
]
p[l]...p[r]
p[l]...p[r]之间是否存在
x
x
x的子孙
思路:考虑DFS序,设点
v
v
v为点
u
u
u的子孙那么
v
v
v的dfs序被u的dfs序完全包含。每个点去映射自身的DFS序,对于每个点
u
u
u维护开始的时间戳
d
l
[
u
]
dl[u]
dl[u]和结束的时间戳
d
r
[
u
]
dr[u]
dr[u],在该区间内的节点为该点的子孙。
同样的对序列P进行映射操作,对于每次区间询问
l
,
r
,
x
l, r,x
l,r,x,只需要维护区间
[
l
,
r
]
[l,r]
[l,r]之间数值在
[
d
l
[
x
]
,
d
r
[
x
]
]
[dl[x],dr[x]]
[dl[x],dr[x]]的个数即可。
通过主席树可以快速维护,(好像就是板子题)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, q, p[N];
inline int read()
{
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=(x<<3)+(x<<1)+(c^48);
c=getchar();
}
return x*f;
}
inline void write(int x){
if(x<0)
putchar('-'),x=-x;
if(x>9)
write(x/10);
putchar(x%10+'0');
return;
}
struct graph
{
int cnte, hd[N];
struct edge
{
int v, nt;
/* data */
} e[N << 1];
inline void addedge(int u, int v)
{
e[++cnte].v = v;
e[cnte].nt = hd[u];
hd[u] = cnte;
}
/* data */
} g;
int dfn[N], tim = 0, dfe[N];
inline void dfs(int u, int f)
{
// cout << "dfs " << u << "\n";
dfn[u] = ++tim;
for (int i = g.hd[u]; i; i = g.e[i].nt)
{
int v = g.e[i].v;
if (v != f)
{
dfs(v, u);
}
}
dfe[u] = tim;
}
struct smg
{
int rt[N], cnt = 0;
struct tree
{
int ls, rs;
int sum;
/* data */
} tr[N * 20];
inline void updata(int pre, int &now, int l, int r, int pos)
{
now = ++cnt;
// tr[cnt].ls = 0;
// tr[cnt].rs = 0;
// tr[cnt].sum = 0;
tr[now] = tr[pre];
tr[now].sum++;
if (l == r)
{
return;
}
int m = l + r >> 1;
if (pos <= m)
{
updata(tr[pre].ls, tr[now].ls, l, m, pos);
}
else
{
updata(tr[pre].rs, tr[now].rs, m + 1, r, pos);
}
// cout <<"updata "<< now << " " << tr[now].ls << " " << tr[now].rs << " " << tr[now].sum <<" "<<l<<" "<<r<< "\n";
}
inline void build()
{
cnt = 0;
for (int i = 1; i <= n; i++)
{
rt[i] = 0;
updata(rt[i - 1], rt[i], 1, n, p[i]);
}
}
inline int query(int pre, int now, int l, int r, int pl, int pr)
{ // 区间小于个数
if (pl <= l && r <= pr)
{
return tr[now].sum - tr[pre].sum;
}
int m = l + r >> 1;
int res = 0;
if (pl <= m)
{
res += query(tr[pre].ls, tr[now].ls, l, m, pl, pr);
}
if (pr > m)
{
res += query(tr[pre].rs, tr[now].rs, m + 1, r, pl, pr);
}
return res;
}
/* data */
} smg;
inline void init()
{
tim = g.cnte = 0;
for (int i = 1; i <= n; i++)
{
g.hd[i] = 0;
}
}
inline void solve()
{
// cin >> n >> q;
n = read();
q = read();
init();
for (int u, v, i = 1; i < n; i++)
{
// cin >> u >> v;
u = read();
v = read();
g.addedge(u, v);
g.addedge(v, u);
}
for (int i = 1; i <= n; i++)
{
// cin >> p[i];
p[i] = read();
}
dfs(1, 0);
for (int i = 1; i <= n; i++)
{
p[i] = dfn[p[i]];
}
smg.cnt = 0;
smg.build();
smg.tr[0].ls = 0;
smg.tr[0].rs = 0;
smg.tr[0].sum = 0;
int l, r, x;
for (int i = 1; i <= q; i++)
{
// cin >> l >> r >> x;
l = read();
r = read();
x = read();
int pl = dfn[x];
int pr = dfe[x];
int sum = smg.query(smg.rt[l - 1], smg.rt[r], 1, n, pl, pr);
// cout << l << " " << r << " " << pl << " " << pr << " " << sum << "\n";
if (sum > 0)
{
// cout << "YES\n";
printf("YES\n");
}
else
{
// cout << "NO\n";
printf("NO\n");
}
}
printf("\n");
}
int main()
{
ios::sync_with_stdio(0);
cout.tie(0);
cin.tie(0);
int t = 1;
// cin >> t;
t = read();
while (t--)
{
solve();
}
}