HDU3974 Assign the task —— dfs时间戳 + 线段树
题目链接:https://vjudge.net/problem/HDU-3974
The company usually assigns some tasks to some employees to finish.When a task is assigned to someone,He/She will assigned it to all his/her subordinates.In other words,the person and all his/her subordinates received a task in the same time. Furthermore,whenever a employee received a task,he/she will stop the current task(if he/she has) and start the new one.
Write a program that will help in figuring out some employee’s current task after the company assign some tasks to some employee.
InputThe first line contains a single positive integer T( T <= 10 ), indicates the number of test cases.
For each test case:
The first line contains an integer N (N ≤ 50,000) , which is the number of the employees.
The following N - 1 lines each contain two integers u and v, which means the employee v is the immediate boss of employee u(1<=u,v<=N).
The next line contains an integer M (M ≤ 50,000).
The following M lines each contain a message which is either
"C x" which means an inquiry for the current task of employee x
or
"T x y"which means the company assign task y to employee x.
(1<=x<=N,0<=y<=10^9)OutputFor each test case, print the test case number (beginning with 1) in the first line and then for every inquiry, output the correspond answer per line.Sample Input
1 5 4 3 3 2 1 3 5 2 5 C 3 T 2 1 C 3 T 3 2 C 3
Sample Output
Case #1: -1 1 2
题解:
1.可知:对一棵树进行dfs(前序遍历),并为每个结点分配一个时间戳,表明该结点是第几个被访问的结点。对于某一个结点(非叶子),它的所有子孙的遍历次序是紧跟着当前节点的。
2.根据时间戳dfn[u],把每个结点u映射到一维数组上。设le[u]为子树u开始访问的时间戳,可知le[u]=dfn[u];ri[u]为子树u结束访问的时间戳,可知ri[u]为结点u最后被访问的子孙的时间戳。所以结点u的作用域就是: [ le[u], ri[u] ]。因此,我们就可以用线段树的区间修改来进行维护了。
学习之处:
根据DFS的特性:对一棵树进行先序遍历,对于当前结点u,它的所有子孙的遍历次序是紧跟着当前节点的。
因此,我们可以根据时间戳,把一棵树映射到到一维数组上,且可以知道每棵子树的确切位置。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const double EPS = 1e-8; 15 const int INF = 2e9; 16 const LL LNF = 2e18; 17 const int MAXN = 5e4+10; 18 19 vector<int>g[MAXN]; 20 int have_fa[MAXN]; 21 int index, dfn[MAXN], le[MAXN], ri[MAXN]; 22 int task[MAXN<<2]; 23 24 void dfs(int u) 25 { 26 dfn[u] = le[u] = ++index; 27 for(int i = 0; i<g[u].size(); i++) 28 dfs(g[u][i]); 29 ri[u] = index; 30 } 31 32 void push_down(int u) 33 { 34 if(task[u]!=-1) 35 { 36 task[u*2] = task[u*2+1] = task[u]; 37 task[u] = -1; 38 } 39 } 40 41 void set_val(int u, int l, int r, int x, int y, int val) 42 { 43 if(x<=l && r<=y) 44 { 45 task[u] = val; 46 return; 47 } 48 49 push_down(u); 50 int mid = (l+r)>>1; 51 if(x<=mid) set_val(u*2, l, mid, x, y, val); 52 if(y>=mid+1) set_val(u*2+1, mid+1, r, x, y, val); 53 } 54 55 int query(int u, int l, int r, int x) 56 { 57 if(l==r) return task[u]; 58 59 push_down(u); 60 int mid = (l+r)>>1; 61 if(x<=mid) return query(u*2, l, mid, x); 62 else return query(u*2+1, mid+1, r, x); 63 } 64 65 int main() 66 { 67 int n, m, T; 68 scanf("%d", &T); 69 for(int kase = 1; kase<=T; kase++) 70 { 71 scanf("%d", &n); 72 for(int i = 1; i<=n; i++) 73 g[i].clear(), have_fa[i] = 0; 74 for(int i = 1; i<n; i++) 75 { 76 int u, v; 77 scanf("%d%d", &u, &v); 78 g[v].push_back(u); 79 have_fa[u] = 1; 80 } 81 82 index = 0; 83 for(int i = 1; i<=n; i++) 84 if(!have_fa[i]) 85 dfs(i); 86 87 scanf("%d", &m); 88 memset(task, -1, sizeof(task)); 89 printf("Case #%d:\n", kase); 90 for(int i = 1; i<=m; i++) 91 { 92 char op[2]; int x, y; 93 scanf("%s", op); 94 if(op[0]=='T') 95 { 96 scanf("%d%d", &x, &y); 97 set_val(1, 1, n, le[x], ri[x], y); 98 } 99 else 100 { 101 scanf("%d", &x); 102 printf("%d\n", query(1, 1, n, dfn[x])); 103 } 104 } 105 } 106 }