http://acm.hdu.edu.cn/showproblem.php?pid=3974

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

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.

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


C
T
C
T
C

Sample Output

Case #:
-

题意:

公司中有N个职员,只有一个老板,其余每个职员对应一个上司,这N个职员刚好组成一棵树。然后有M个操作。

当给一个职员x分配任务y时(即 T x y),x及其下属及其下属的下属都会放下手头的工作去完成任务y。对于每次询问(即C x),程序输出职员x正在进行什么任务。

简而言之:给出一个有向多叉树,初始所有节点为-1.有两种操作,一种为(T,x,y),表示将x节点及其的所有子树中的节点变为y,另一种为(C,x),为求x节点的值。

题解:

这道题的难点就在于如何将题中的对应关系转化为线段树的模型,在于如何处理好多叉树和线段树间的映射关系。

线段树的本质就是对一整段连续区间进行操作。所以这道题的关键就在于清楚怎么将对多叉树的操作转化成对一整段连续区间的操作。

很明显该公司的所有员工间的关系可以用一颗多叉树来表示。然后从公司老板(也就是入度为0的点)出发,用dfs给这棵树打上时间戳,确定每个点的影响范围并记录下来。

根据新分配的id号码将其节点对应映射到线段树上面。这样分配任务就相当于更新一段连续的节点,查询任务相当于单点查询。

代码如下:

 #include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <map>
#include <math.h>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
//const double PI=acos(-1);
const int maxn=1e5+;
using namespace std;
//ios::sync_with_stdio(false);
// cin.tie(NULL); struct Edge_node
{
int v;
int next;
}Edge[*]; struct SegTree_node
{
int l;
int r;
int num;
}SegTree[<<];
int n,m;
int cnt;//边的计数器,从0开始
int num;//线段树序号的计数器,从1开始
int head[];
int vis[];//是否有上司,即入度为0
int st[];//开始遍历时的编号,同时作为线段树中的序号
int ed[];//遍历结束后的序号,表示该点在线段树中可以影响的最后一个序号(即上司) void init()//初始化
{
cnt=;
num=;
memset(head,-,sizeof(head));
memset(st,,sizeof(st));
memset(ed,,sizeof(ed));
memset(Edge,,sizeof(Edge));
memset(vis,,sizeof(vis));
} void add_edge(int u,int v)
{
Edge[cnt].v=v;
Edge[cnt].next=head[u];
head[u]=cnt++;
} void DFS(int u)
{
num++;
st[u]=num;
for(int i=head[u];i!=-;i=Edge[i].next)
{
DFS(Edge[i].v);
}
ed[u]=num;
} void PushDown(int rt)
{
if(SegTree[rt].num!=-)
{
SegTree[rt<<].num=SegTree[rt<<|].num=SegTree[rt].num;
SegTree[rt].num=-;
}
} void Build(int l,int r,int rt)
{
SegTree[rt].l=l;
SegTree[rt].r=r;
SegTree[rt].num=-;
if(l==r)
return ;
int mid=(l+r)>>;
Build(l,mid,rt<<);
Build(mid+,r,rt<<|);
} void Update(int L,int R,int C,int rt)
{
int l=SegTree[rt].l;
int r=SegTree[rt].r;
if(L<=l&&R>=r)
{
SegTree[rt].num=C;
return ;
}
PushDown(rt);
int mid=(l+r)>>;
if(L<=mid)
Update(L,R,C,rt<<);
if(R>mid)
Update(L,R,C,rt<<|);
} int Query(int L,int rt)
{
int l=SegTree[rt].l;
int r=SegTree[rt].r;
if(l==r)
return SegTree[rt].num;
PushDown(rt);
int mid=(l+r)>>;
if(L<=mid)
Query(L,rt<<);
else if(L>mid)
Query(L,rt<<|);
} int main()
{
int T;
scanf("%d",&T);
for(int k=;k<=T;k++)
{
printf("Case #%d:\n",k);
init();
scanf("%d",&n);
for(int i=;i<n;i++)
{
int u,v;
scanf("%d %d",&u,&v);
vis[u]=;
add_edge(v,u);
}
for(int i=;i<=n;i++)
{
if(!vis[i])
{
DFS(i);
break;
}
}
Build(,num,);
scanf("%d",&m);
for(int i=;i<=m;i++)
{
char c[];
int x;
scanf("%s %d",c,&x);
if(c[]=='C')
{
printf("%d\n",Query(st[x],));
}
else if(c[]=='T')
{
int t;
scanf("%d",&t);
//st[x]->ed[x]代表x及x的下属在线段树中的区间范围
Update(st[x],ed[x],t,);
}
}
}
return ;
}

HDU-3974 Assign the task(多叉树DFS时间戳建线段树)的更多相关文章

  1. HDU 3974 Assign the task 暴力/线段树

    题目链接: 题目 Assign the task Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...

  2. HDU 3974 Assign the task (DFS序 + 线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3974 给你T组数据,n个节点,n-1对关系,右边的是左边的父节点,所有的值初始化为-1,然后给你q个操 ...

  3. HDU 3974 Assign the task(DFS序+线段树单点查询,区间修改)

    描述There is a company that has N employees(numbered from 1 to N),every employee in the company has a ...

  4. hdu 3974 Assign the task(dfs序上线段树)

    Problem Description There is a company that has N employees(numbered from 1 to N),every employee in ...

  5. HDU 3974 Assign the task(DFS序)题解

    题意:给出一棵树,改变树的一个节点的值,那么该节点及所有子节点都变为这个值.给出m个询问. 思路:DFS序,将树改为线性结构,用线段树维护.start[ ]记录每个节点的编号,End[ ]为该节点的最 ...

  6. HDU 3974 Assign the task (DFS+线段树)

    题意:给定一棵树的公司职员管理图,有两种操作, 第一种是 T x y,把 x 及员工都变成 y, 第二种是 C x 询问 x 当前的数. 析:先把该树用dfs遍历,形成一个序列,然后再用线段树进行维护 ...

  7. HDU - 3974 Assign the task (DFS建树+区间覆盖+单点查询)

    题意:一共有n名员工, n-1条关系, 每次给一个人分配任务的时候,(如果他有)给他的所有下属也分配这个任务, 下属的下属也算自己的下属, 每次查询的时候都输出这个人最新的任务(如果他有), 没有就输 ...

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

    Assign the task Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?p ...

  9. HDU 3974 Assign the task(简单线段树)

    Assign the task Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

随机推荐

  1. PHP集成环境wamp和navicat for mysql 的安装

    1. PHP集成环境WAMP的安装: 下载wamp: 链接:https://pan.baidu.com/s/1zvoPEbLdG7y04WWHNM6UcA  密码:mxd3 安装过程如下图: 安装完成 ...

  2. LeetCode随想------Single Number-----关于异或的性质

    异或满足交换律,结合律 任何数X^X=0,X^0=X 自反性 A XOR B XOR B = A xor  0 = A  设有A,B两个变量,存储的值分别为a,b,则以下三行表达式将互换他们的值 表达 ...

  3. java课程之团队开发之用户模板和用户场景

    用户模板与用户场景: 姓名:孙某 性别年龄:男 19岁 职业;学生 收入:无 知识层次能力:大学生,用电脑熟练. 生活/工作状况:正常进行上课,学霸. 动机目的,困难:喜欢依据自己的兴趣进行学习. 用 ...

  4. {转} 深入理解 HTTP Session

    session在web开发中是一个非常重要的概念,这个概念很抽象,很难定义,也是最让人迷惑的一个名词,也是最多被滥用的名字之一,在不同的场合,session一次的含义也很不相同.这里只探讨HTTP S ...

  5. windows和ubuntu双系统设置开机默认系统

    1.记住grub界面中windows的位置 我的界面如下:windows在第3行 2.选择进入ubuntu系统 3.打开终端,输入如下命令 sudo vim /etc/default/grub 4.看 ...

  6. MySQL空洞问题解决

    原因:Mysql对于BLOB/TEXT值在执行大量删除操作时可能会引起空洞.空洞就是数据虽然删除了,但是依然占用服务器物理空间,会导致性能底下. 解决办法:定期使用OPTIMIZE TABLE进行碎片 ...

  7. 【leetcode困难】968. 监控二叉树

    968. 监控二叉树 瞎**分析评论区Rui大佬的答案,这题想直接递归return min还是有坑的,分计数和状态.有个状态转换的思想

  8. cppcheck下载及使用

    一.参考文档 1.Ubuntu下安装Cppcheck源码操作步骤 2.cppcheck std.cfg not found error when std.cfg file is available 3 ...

  9. Python基础学习一

    Python基础学习一 1.变量与常量 变量名:大小写英文.数字.下划线的组合,数字不能开头 常量名:习惯上常量用大写字母命名,例如"PI" 2.多行输出 转义符:反斜杠(),如果 ...

  10. 在线公开课 | 5G时代的视频云服务关键技术与实践

    5G时代来临在即,视频技术将会如何发展呢?基于视频云服务的技术开发又有怎样的变化呢?为此,京东云视频云产品研发部高级总监魏伟为大家做出了详细解读. 魏伟拥有10多年视频行业研发经验,先后从事于AVS标 ...