HDU 3974 Assign the task(线段树)

描述
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.

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)

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

题意

有N个雇员,然后有N-1行每行u,v代表v是u的老板,当老板有任务时,他会让他的下属一起做这个任务

有M个操作,操作C代表询问雇员X当前的任务是什么,没有输出-1,操作T代表给雇员X一个任务Y

题解

首先可以看出一个关系树,我们知道dfs时间戳可以知道每个节点为根开始访问的第一个节点(本身)s和最后一个节点e

然后我们用线段树去维护

对于操作C,我们直接单点s[x]查询

对于操作T,我们通过dfs序,区间[s[x],e[x]]修改延迟标记

代码

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<vector>
 4 using namespace std;
 5
 6 const int N=5e4+5;
 7
 8 int n,ans;
 9 int s[N],e[N],vis[N],tot;
10 int lazy[N<<2];
11 vector<int>G[N];
12
13 void PushDown(int rt)
14 {
15     if(lazy[rt]!=-1)
16     {
17         lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
18         lazy[rt]=-1;
19     }
20 }
21
22 void Update(int L,int R,int task,int l,int r,int rt)
23 {
24     if(L<=l&&r<=R)
25     {
26         lazy[rt]=task;
27         return;
28     }
29     int mid=(l+r)>>1;
30     PushDown(rt);
31     if(L<=mid)Update(L,R,task,l,mid,rt<<1);
32     if(R>mid)Update(L,R,task,mid+1,r,rt<<1|1);
33 }
34
35 void Query(int L,int l,int r,int rt)
36 {
37     if(L==l&&L==r)
38     {
39         ans=lazy[rt];
40         return;
41     }
42     int mid=(l+r)>>1;
43     PushDown(rt);
44     if(L<=mid)Query(L,l,mid,rt<<1);
45     else Query(L,mid+1,r,rt<<1|1);
46 }
47
48 void dfs(int u)
49 {
50     tot++;
51     s[u]=tot;
52     for(auto X:G[u])dfs(X);
53     e[u]=tot;
54 }
55
56 int main()
57 {
58     int t,q,u,v,x,y,o=1;
59     char op[3];
60     scanf("%d",&t);
61     while(t--)
62     {
63         printf("Case #%d:\n",o++);
64         memset(vis,0,sizeof vis);
65         memset(lazy,-1,sizeof lazy);
66         scanf("%d",&n);
67         for(int i=1;i<=n;i++)G[i].clear();
68         for(int i=1;i<n;i++)
69         {
70             scanf("%d%d",&u,&v);
71             vis[u]=1;
72             G[v].push_back(u);
73         }
74         ///dfs序
75         for(int i=1;i<=n;i++)
76             if(!vis[i]){tot=0;dfs(i);break;}
77         scanf("%d",&q);
78         for(int i=0;i<q;i++)
79         {
80             scanf("%s",op);
81             if(op[0]==‘C‘)
82             {
83                 scanf("%d",&x);
84                 Query(s[x],1,n,1);
85                 printf("%d\n",ans);
86             }
87             if(op[0]==‘T‘)
88             {
89                 scanf("%d%d",&x,&y);
90                 Update(s[x],e[x],y,1,n,1);
91             }
92         }
93     }
94     return 0;
95 }

原文地址:https://www.cnblogs.com/taozi1115402474/p/9286724.html

时间: 2024-08-02 21:29:01

HDU 3974 Assign the task(线段树)的相关文章

hdu 3974 Assign the task 线段树 DFS序

给你一棵树,每次修改一个子树的所有值,然后单点查询. 按照DFS序把节点排列(即在DFS中出现的先后次序),同一个子树在序列中连续. 1 #include <cstdio> 2 using namespace std; 3 typedef long long ll; 4 int n,q,T,Tc,cnt,sum; 5 int col[210000],lzy[210000],sta[51000],fin[51000]; 6 int nxt[51000],to[51000],head[51000]

HDU 3974 Assign the task 并查集/图论/线段树

Assign the task Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3974 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 l

hdu 3974 Assign the task(线段树)

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3974 题意:给定一棵树,50000个节点,50000个操作,C x表示查询x节点的值,T x y表示更新x节点及其子节点的值为y 大致把边存一下那一棵树来举例子 2 3 5 4 1 例如像这样的一棵树,可以将2->1,3->2,4->3,1->4,5->5按照dfs序来编号,然后用线段树进行区间修改,稍微想一想 应该都会了. #include <iostream> #

HDU - 3974 Assign the task (线段树区间修改+构建模型)

https://cn.vjudge.net/problem/HDU-3974 题意 有一棵树,给一个结点分配任务时,其子树的所有结点都能接受到此任务.有两个操作,C x表示查询x结点此时任务编号,T x y表示给x结点分配编号为y的任务. 分析 题目读起来就很有区间修改的味道,将一个区间变为一个值.问题在于怎么把这棵树对应到区间上. 对于一个结点,其控制的范围是它的子树,对应区间范围可以看作是以dfs序表示的区间.好像有点绕..就是给每个结点再对应一个dfs序,然后在dfs时把这个点控制的子树看

HDU 3974 Assign the task(树 并查集)

题意  公司中有n个员工  除了boss  每个员工都有自己的上司  自己下属的下属也是自己的下属  当给一个员工分配任务时  这个员工会把任务也分配到自己的所有下属   每个员工都只做最后一个被分配的任务  对于每个C x  输出员工x正在做的任务  没有就输出-1 把员工的关系数建成类似并查集的结构  把每个直接分配任务的员工的任务和任务分配时间保存起来  查询时只要找这个员工所有父节点中最晚分配的任务 #include <bits/stdc++.h> using namespace st

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 时间戳 -

HDU 3974 Assign the task(dfs编号+线段树成段更新)

题意:给定点的上下级关系,规定如果给i分配任务a,那么他的所有下属.都停下手上的工作,开始做a. 操作 T x y 分配x任务y,C x询问x的当前任务: 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 思路: 利用dfs深度优先遍历重新编号,使一个结点的儿子连续.然后成段更新. 2:1-5 5:2-2 3:3-5 1:4-4 4:5-5 #include<iostr

HDU 3974 Assign the task(dfs时间戳+线段树成段更新)

题意:给定点的上下级关系,规定假设给i分配任务a.那么他的全部下属.都停下手上的工作,開始做a. 操作 T x y 分配x任务y,C x询问x的当前任务: 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 思路: 利用dfs深度优先遍历又一次编号.使一个结点的儿子连续. 然后成段更新. 代码: #include<iostream> #include<cstdio

HDU 3974 Assign the task(并查集)

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, an