用深搜去求出每个点管辖的子树在线段树上所对应的区间,然后进行常规修改、查询即可
#include <bits/stdc++.h>
//#pragma GCC optimize(3, "Ofast", "inline")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 100010;
int w[N], e[N], ne[N], h[N], idx;
int T, n, ml[N], mr[N];
int father[N];
struct node
{
int l, r, x;
}tr[N * 4];
void add(int a, int b) // 存要维护的图
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void push_down(int u) // 懒标记下放操作
{
if (tr[u].x != -1)
{
tr[u << 1].x = tr[u].x;
tr[u << 1 | 1].x = tr[u].x;
tr[u].x = -1;
}
}
void build(int u, int l, int r)
{
if (l == r)
tr[u] = {l, r, -1};
else
{
tr[u] = {l, r, -1};
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
}
}
int cnt;
void dfs(int u) // 跑一遍深搜去求出每个点的子树在线段树中所对应的区间
{
ml[u] = ++ cnt;
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
dfs(j);
}
mr[u] = cnt;
}
void modify(int u, int l, int r, int k)
{
if (tr[u].l >= l && tr[u].r <= r)
{
tr[u].x = k;
}
else
{
push_down(u);
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid) modify(u << 1, l, r, k);
if (r > mid) modify(u << 1 | 1, l, r, k);
}
}
int query(int u, int x)
{
if (tr[u].l == x && tr[u].r == x)
return tr[u].x;
else
{
push_down(u);
int mid = tr[u].l + tr[u].r >> 1;
int res;
if (x <= mid) res = query(u << 1, x);
if (x > mid) res = query(u << 1 | 1, x);
return res;
}
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int res = 0;
cin >> T;
while (T --)
{
cout << "Case #" << ++ res << ":\n";
memset(h, -1, sizeof(h));
memset(father, 0, sizeof(father));
idx = 0;
cin >> n;
for (int i = 1; i < n; i ++)
{
int a, b;
cin >> a >> b;
add(b, a);
father[a] = b;
}
int root = 1;
while (father[root]) root ++; // 找到根节点
cnt = 0;
dfs(root);
build(1, 1, n);
int q;
cin >> q;
while (q --)
{
char ch;
cin >> ch;
if (ch == 'C')
{
int x;
cin >> x;
cout << query(1, ml[x]) << '\n';
}
else
{
int x, y;
cin >> x >> y;
modify(1, ml[x], mr[x], y);
}
}
}
return 0;
}