题意:
有一个公司,有n个人;
这些人之间的关系是一棵树;
即:有的人是老板,有的人是员工,有的人既是老板,又是员工;
然后公司随时都会安排一些工作给他们做;
每次安排至安排一个人,但是他的下属会和他一起做;
题目就是查询当前这个人在做什么工作;
理解:
这个题的题意好理解,读几遍就知道了
但是对于已知的关系;
即:画出的公司员工之间的那棵树;
我是在无法联想到线段树;
之前还想怎么减小时间复杂度,然后暴力解决;
结果肯定是不行的;
所以只有向线段树想;
于是发现;
在分配了任务之后;
只有当前这个人和他的员工在做这个工作;
那么如果把这群人平铺下来;
即:把做一个工作的人放在一起,老板放在最前面;
然后发现;
通过这样做之后;
对于更新当前员工;
即是对他和他的下属的更新;
于是就是对上述平铺的数组中的某个区间进行更新;
这样就可以用到线段树了;
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const double MIN_INF = 1e-7;
const int MAX_INF = (1e9) + 7;
#define X first
#define Y second
int tree[50005 * 4], add[50005 * 4];
void build(int rx, int l, int r) {
if (l == r) {
tree[rx] = -1;
return ;
}
build(rx * 2, l, (l + r) / 2);
build(rx * 2 + 1, (l + r) / 2 + 1, r);
tree[rx] = -1;
}
void push_down(int rx) {
tree[rx * 2] = tree[rx * 2 + 1] = add[rx];
add[rx * 2] = add[rx * 2 + 1] = add[rx];
add[rx] = -1;
}
void update(int rx, int L, int R, int l, int r, int y) {
if (add[rx] != -1) {
push_down(rx);
}
if (L >= l && r >= R) {
add[rx] = y;
tree[rx] = y;
return ;
}
if (L > r || l > R) {
return ;
}
update(rx * 2, L, (L + R) / 2, l, r, y);
update(rx * 2 + 1, (L + R) / 2 + 1, R, l, r, y);
}
int query(int rx, int L, int R, int l, int r) {
if (add[rx] != -1) {
push_down(rx);
}
if (L >= l && r >= R) {
return tree[rx];
}
if (L > r || l > R) {
return -2;
}
int ans1 = query(rx * 2, L, (L + R) / 2, l, r);
int ans2 = query(rx * 2 + 1, (L + R) / 2 + 1, R, l, r);
if (ans1 != -2) {
return ans1;
}
else {
return ans2;
}
}
void solve(vector<vector<int> > &vec, vector<int> &idl, vector<int> &len, int root, int &pos) {
idl[root] = pos;
for (int i = 0; i < vec[root].size(); ++i) {
solve(vec, idl, len, vec[root][i], ++pos);
len[root] += len[vec[root][i]];
}
len[root] += vec[root].size();
}
int main() {
int t;
cin >> t;
for (int I = 1; I <= t; ++I) {
memset(tree, -1, sizeof tree);
memset(add, -1, sizeof add);
int n;
scanf("%d", &n);
vector<vector<int> > vec(n + 2);
vector<int> idl(n + 2, 0), len(n + 2, 0);
for (int i = 0; i < n - 1; ++i) {
int u, v;
scanf("%d%d", &u, &v);
vec[v].push_back(u);
idl[u] = 1;
}
int root, pos = 1;
for (int i = 1; i <= n; ++i) {
if (idl[i] != 1) {
root = i;
}
}
solve(vec, idl, len, root, pos);
printf("Case #%d:\n", I);
build(1, 1, n);
int m;
scanf("%d", &m);
while (m--) {
string str;
cin >> str;
if (str[0] == 'T') {
int x, y;
scanf("%d%d", &x, &y);
update(1, 1, n, idl[x], idl[x] + len[x], y);
}
else {
int x;
scanf("%d", &x);
int ans = query(1, 1, n, idl[x], idl[x] + len[x]);
printf("%d\n", ans);
}
}
}
return 0;
}