HDU 3974 Assign the task
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3974
解题思路:深搜设置时间戳,然后线段树上更新查询即可。
第一次写,还算顺利(尽管wa了两发)。
代码:
1 const int maxn = 5e4 + 5; 2 //静态链表前向星保存图 3 struct Edge{ 4 int to, next; 5 int val; 6 }; 7 int head[maxn], tot; 8 Edge edges[maxn]; 9 //dfs 时间戳 - st 表示开始时间, ed 表示结束时间, cnt 总的节点个数 10 int st[maxn], ed[maxn], cnt; 11 int tree[maxn * 4], ass[maxn * 4], vis[maxn];//tree 线段树节点值, ass 区间更新延迟标记, vis 查找根节点用 12 int n, m; 13 14 void init(){ 15 memset(head, -1, sizeof(head)); 16 memset(tree, -1, sizeof(tree)); 17 memset(ass, -1, sizeof(ass)); 18 memset(vis, 0, sizeof(vis)); 19 tot = 0; 20 cnt = 0; 21 } 22 void addEdge(int u, int v, int w){ 23 edges[tot].to = v; 24 edges[tot].val = w; 25 edges[tot].next = head[u]; 26 head[u] = tot++; 27 } 28 //深度优先搜索为每个节点设置时间戳 29 //画个图很容易看到对应区间关系,父节点区间总是包含子节点的区间 30 //在线段树的节点中,叶子节点对应的标号是每个节点的起始时间st[u] 31 void dfs(int u){ 32 cnt++; 33 //起始时间 34 st[u] = cnt; 35 for(int i = head[u]; i != -1; i = edges[i].next){ 36 //对子节点深搜 37 dfs(edges[i].to); 38 } 39 //结束时间 40 ed[u] = cnt; 41 } 42 void build(int l, int r, int k){ 43 if(l == r) { 44 ass[k] = tree[k] = -1; 45 return; 46 } 47 int mid = (l + r) >> 1, lc = k << 1, rc = k << 1; 48 build(l, mid, lc); 49 build(mid + 1, r,rc); 50 } 51 //延迟标记ass,初始为-1,每次update或者query时要pushdown到子节点 52 void update(int ul, int ur, int x, int l, int r, int k){ 53 if(ul == l && ur == r){ 54 ass[k] = x; 55 return; 56 } 57 if(ul > r || ur < l) return; 58 if(l == r){ 59 tree[k] = x; 60 ass[k] = -1; 61 return; 62 } 63 64 int lc = k << 1, rc = k << 1 | 1; 65 if(ass[k] != -1){ 66 tree[k] = ass[k]; 67 ass[lc] = ass[k]; 68 ass[rc] = ass[k]; 69 ass[k] = -1; 70 } 71 72 int mid = (l + r) >> 1; 73 update(ul, ur, x, l, mid, lc); 74 update(ul, ur, x, mid + 1, r, rc); 75 } 76 77 int query(int qu, int l, int r, int k){ 78 if(l == qu && r == qu){ 79 if(ass[k] != -1){ 80 tree[k] = ass[k]; 81 return ass[k]; 82 } 83 return tree[k]; 84 } 85 int lc = k << 1, rc = k << 1 | 1; 86 if(ass[k] != -1){ 87 tree[k] = ass[k]; 88 ass[lc] = ass[k]; 89 ass[rc] = ass[k]; 90 ass[k] = -1; 91 } 92 93 94 int mid = (l + r) >> 1; 95 if(qu <= mid) return query(qu, l, mid, lc); 96 else return query(qu, mid + 1, r, rc); 97 } 98 99 int main(){ 100 int T; 101 scanf("%d", &T); 102 for(int t = 1; t <= T; t++){ 103 printf("Case #%d:\n", t); 104 init(); 105 scanf("%d", &n); 106 for(int i = 2; i <= n; i++){ 107 int u, v; 108 scanf("%d %d", &u, &v); 109 addEdge(v, u, 1); 110 vis[u]++; 111 } 112 for(int i = 1; i <= n; i++){ 113 //从原树根深搜 114 if(vis[i] == 0){ 115 dfs(i); 116 break; 117 } 118 } 119 build(1, cnt, 1); 120 scanf("%d", &m); 121 while(m--){ 122 char ch; 123 scanf(" %c", &ch); 124 if(ch == 'C'){ 125 int x; 126 scanf("%d", &x); 127 //st[x]为原树x节点对应线段树中的节点编号 128 printf("%d\n", query(st[x], 1, cnt, 1)); 129 } 130 else{ 131 int x, y; 132 scanf("%d %d", &x, &y); 133 //更新时[st[], ed[]]包含了原树上x节点以及其所有子节点 134 update(st[x], ed[x], y, 1, cnt, 1); 135 } 136 } 137 } 138 }
题目:
Assign the task
Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3263 Accepted Submission(s): 1340
Problem Description
There is a company that has N employees(numbered from 1 to N),every employee in the company has a immediate boss (except for the leader of whole company).If you are the immediate boss of someone,that person is your subordinate, and all his subordinates are your subordinates as well. If you are nobody's boss, then you have no subordinates,the employee who has no immediate boss is the leader of whole company.So it means the N employees form a tree.
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.
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.
Input
The 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)
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)
Output
For 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
Source