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. swtich多个case使用同一操作

    switch (expression) { case 'status01': case 'status02': case 'status03': alert('resultOne'); break; ...

  2. @SpringBootApplication 标注非引导类

    1.引导类 public class App { public static void main(String[] args) { SpringApplication.run(WebConfigura ...

  3. 越南CTF的crypto 100

    自己做CTF还是没有经验,本来以为crypto更多应该是python编程的,结果这个100的题目是Do you love Arithmetic? 打开文件来看内容是 # charset = " ...

  4. Windbg 实践之符号篇

    How to display the size value 1)一开始不会加载,chksym 了一下就加载了. 2) 新版本已经可以显示size的大小了 3)?? 显示变量的类型 4)x std::v ...

  5. UVA 11732 链表+字典树

    因为字符集比较大,所以就不能用简单字典树,在字典树里面,用链表进行存储.这个倒是不难,练了下手 统计的时候还是有点难搞,因为要算所有的两两比较的次数之和,对分叉处进行计算,注意细节 #include ...

  6. ArrayList扩容原理分析

    1:代码解读和分析 1.1:构造方法分析 1: public ArrayList(int initialCapacity) { ) { this.elementData = new Object[in ...

  7. 安装adobe reader阅读器

    首先  在我的网盘里有那个软件. 安装的教程在这个歌网址:http://www.zhanshaoyi.com/6730.html

  8. 常用的tensorflow函数

    在mask_rcnn常用的函数 1  tf.cast():    https://blog.csdn.net/dss875914213/article/details/86558407 2 tf.ga ...

  9. python获取页面文字信息

    # -*- coding: utf- -*- from selenium import webdriver import time, re,requests,os,time,random,traceb ...

  10. EL表达式和JSTL(二)——BeanUtils工具

    BeanUtils工具 大对数人习惯使用JavaBean的get和set方法来获取和设置JavaBean的属性,但是在Java EE编程的过程中,会经常从配置文件中读取数据,但是从配置文件中读取的数据 ...