题意:
一个公司中有一种制度:如果老板被分配到一个任务,那么他会把任务分配给他的直接员工,员工中如果是其他人的老板,那么该员工的员工也将被分配到这个任务。
这个公司中有 n 个人,给 m 此操作,T x y 代表给 x 分配的任务是 y,C x 代表查询 x 的任务。
题解:
我一开始是没有思路的,看了别人的解题思路才知道,如果对一棵树 dfs 的过程中一个点访问了两次,那么从第一次访问该点到第二次访问该点之间的所有点都是以该点为根节点的子树中的节点。那么建树完成之后 dfs 跑一遍求出该树的的 dfs 序和每一个节点的直接或间接儿子个数(看到有人用时间戳来求个数,感觉自己写复杂了)。这样就可以利用树的 dfs 序来建立一颗线段树了。然后每一次更新,例如将 u 点更新为 y,u 点的所有子孙有num[u]个,那么只需要把 u 到 num[u] 之间的所有点更新为 y 即可。
注意需要利用一个数组来保存每一个点在 dfs 序中的下标才能进行线段树的操作。具体看代码。
代码:
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <bitset>
#define INF 0x3f3f3f3f
#define MAXM 50000 + 10
#define MAXN 50000 + 10
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
int t, n, m;
vector<int> G[MAXN];
int a[MAXN], cnt = 1;
struct TREE{
int id;
int color;
}tree[MAXN<<2];
int father[MAXN];
int id[MAXN];
int num[MAXN];
void dfs(int u, int pre)
{
a[cnt] = u;
id[u] = cnt ++;
num[u] = G[u].size();
for(int i = 0; i < G[u].size(); i ++){
dfs(G[u][i], u);
}
num[pre] += num[u];
}
void push(int rt)
{
if(tree[rt].color != -1){
tree[rt<<1].color = tree[rt].color;
tree[rt<<1|1].color = tree[rt].color;
tree[rt].color = -1;
}
}
void build(int L, int R, int rt)
{
if(L == R){
tree[rt].id = a[L];
return ;
}
int mid = (L + R) / 2;
build(L, mid, rt << 1);
build(mid + 1, R, rt << 1 | 1);
}
void update(int l, int r, int c, int L, int R, int rt)
{
if(l <= L && R <= r){
tree[rt].color = c;
return ;
}
push(rt);
int mid = (L + R) / 2;
if(l <= mid)
update(l, r, c, L, mid, rt << 1);
if(r > mid)
update(l, r, c, mid + 1, R, rt << 1 | 1);
}
void query(int pos, int L, int R, int rt)
{
if(L == R){
printf("%d\n", tree[rt].color);
return ;
}
push(rt);
int mid = (L + R) / 2;
if(pos <= mid)
query(pos, L, mid, rt << 1);
else
query(pos, mid + 1, R, rt << 1 | 1);
}
void init()
{
cnt = 1;
for(int i = 1; i <= n; i ++) G[i].clear();
memset(a, 0, sizeof(a));
memset(father, 0, sizeof(father));
memset(tree, -1, sizeof(tree));
memset(id, 0, sizeof(id));
}
int main()
{
scanf("%d", &t);
for(int i = 1; i <= t; i ++){
printf("Case #%d:\n", i);
scanf("%d", &n);
init();
for(int i = 1; i <= n - 1; i ++){
int a, b; scanf("%d %d", &a, &b);
G[b].push_back(a);
father[a] = b;
}
for(int i = 1; i <= n; i ++){
if(father[i] == 0)
dfs(i, 0);
}
build(1, n, 1);
scanf("%d", &m);
for(int i = 0; i < m; i ++){
char op; scanf(" %c", &op);
if(op == 'C'){
int x; scanf("%d", &x);
query(id[x], 1, n, 1);
}
else{
int x, y; scanf("%d %d", &x, &y);
update(id[x], id[x] + num[x], y, 1, n, 1);
}
}
}
// system("pause");
}
/*
The WAM is F**KING interesting .
*/