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

题解:需要用DFS建树来确立关系, 然后用线段树进行区间覆盖。

DFS建树: 从Boss 开始dfs,通过dfs递归时编号出现的先后顺序来确定某个员工对应的起点与终点。

样例的关系图是这样的

当dfs建树跑完了之后各个节点对应的位置是这样的

其中Start表示这个节点本身的新编号和这个节点管辖区间内的左端点 End表示这个点管辖区间内的右端点

从右边的图中可以看见其中的最上级2号员工(Boss), 他的管辖区间是[1,5],能覆盖所有人的结点, 5号员工他没有下属所以他的End值就等于Start值。

(发布于第二天的修改, 竟然被吐槽写的不好理解, 非要我再加上下面这幅图)

上面这幅图呢就是线段树下的员工状态图了, 假设我们现在对2号员工分配任务y1

那我们就需要对2号员工的管辖区域[1,5]区间的值都修改成y1。

再注意一下 管辖区域的左端点 还代表的这名员工在线段树下的区间下标是多少。

2号员工的管辖区域是[1,5] 所以他就在位置1。

管辖区域的右端点就是自己最多能管到员工的编号。

所以每次对自己的管辖区域进行线段树区域更新操作就可以将每个人的任务分配下去了。

这样每次查询某个员工的任务的时候只需要将lazy标记推到底,就能找到最后收到的任务了。

用DFS去访问每个节点,并将访问的顺序编号,当DFS遍历了整个关系图之后,每个人的管辖区间就确定下来了,然后就可以通过管辖区间来进行线段树区域覆盖和单点查询操作。

 int cnt = ;
void dfs(int n)
{
Start[n] = ++cnt;
int m = son[n].size();
for(int i = ; i < m; i++)
dfs(son[n][i]);//已经用vector son[n] 来存好了每个人的下属
End[n] = cnt;
}
 #include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<cstring>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int N = +;
vector<int> son[N];
int Start[N], End[N];
int tree[N<<], lazy[N<<];
bool vis[N];
int cnt = ;
void dfs(int n)
{
Start[n] = ++cnt;
int m = son[n].size();
for(int i = ; i < m; i++)
dfs(son[n][i]);
End[n] = cnt;
}
void PushDown(int rt)
{
if(lazy[rt] != -)
{
tree[rt<<] = tree[rt<<|] = lazy[rt<<|] = lazy[rt<<] = lazy[rt];
lazy[rt] = -;
}
}
void Revise(int L, int R, int C, int l, int r, int rt)
{
if(L <= l && r <= R)
{
lazy[rt] = tree[rt] = C;
return ;
}
PushDown(rt);
int m =l+r >> ;
if(L <= m) Revise(L,R,C,lson);
if(m < R) Revise(L,R,C,rson);
}
int Query(int L, int l, int r, int rt)
{
if(l == r)
{
return tree[rt];
}
int m = l+r >> ;
PushDown(rt);
if(L <= m) return Query(L,lson);
else return Query(L,rson);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie();
cout.tie();
int T;
cin >> T;
for(int i = ; i <= T; i++)
{
cout << "Case #" << i << ":\n";
int n, u, v;
cnt = ;
cin >> n;
for(int i = ; i <= n; i++)
son[i].clear(), vis[i] = ;
for(int i = ; i < n; i++)
{
cin >> u >> v;
son[v].push_back(u);//用vector去对应的关系
vis[u] = ;//如果某个点成为过下属就标记一下 没有标记过的那个人就是Boss(最上级)
}
int pos = -;
for(int i = ; i <= n; i++)
if(vis[i])
{
pos = i;
break;
}
dfs(pos);//从最上级的人开始递归, 找到每个人对应的区间
memset(tree, -, sizeof(tree));//因为没有接到任务过的人查询的时候输出-1
memset(lazy, -, sizeof(lazy));//所以直接memset为-1就好了,不需要再进行特判
int t;
cin >> t;
string str;
int x, y;
while(t--)
{
cin >> str;
if(str[] == 'C')
{
cin >> x;
cout << Query(Start[x],,cnt,) << endl;
}
else
{
cin >> x >> y;
Revise(Start[x],End[x],y,,cnt,);
}
}
}
return ;
}

HDU - 3974 Assign the task (DFS建树+区间覆盖+单点查询)的更多相关文章

  1. 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 ...

  2. HDU 3974 Assign the task(dfs建树+线段树)

    题目大意:公司里有一些员工及对应的上级,给出一些员工的关系,分配给某员工任务后,其和其所有下属都会进行这项任务.输入T表示分配新的任务, 输入C表示查询某员工的任务.本题的难度在于建树,一开始百思不得 ...

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

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

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

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

  5. HDU.1556 Color the ball (线段树 区间更新 单点查询)

    HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...

  6. HDU 3974 Assign the task

    Assign the task Problem Description There is a company that has N employees(numbered from 1 to N),ev ...

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

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

  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. KD-tree 专题「Hide and Seek · 巧克力王国」

    Lockey的瞎理解 抄了一遍板子又水了俩题,感觉对KD-tree 稍稍理解了一点儿,唠叨一下(二维的KD-tree),如有错误请指出(Lockey 洗脸恭听) 普通平衡树维护的是一维的序列,但对于二 ...

  2. Docker最简单入门之(二)——简单使用Docker

    0.前言 本章主要写一些怎么使用Docker,拉取镜像和创建容器等之类的Docker的常用基本操作.在开始写之前,大家需要明白一下几个名词的含义 1.镜像:镜像是指一个类似于安装包的东西,尝试安装过电 ...

  3. [TCP/IP]DNS解析

    DNS解析主机的IP地址 host -t A www.baidu.com

  4. Spark 系列(五)—— Spark 运行模式与作业提交

    一.作业提交 1.1 spark-submit Spark 所有模式均使用 spark-submit 命令提交作业,其格式如下: ./bin/spark-submit \ --class <ma ...

  5. mybatis学习笔记(二)

    三种查询方式,由<resultType 属性控制> 第一种 selectList() 返回值为LIst List<People> selectList = session.se ...

  6. 守望先锋app(2)

    上次的功能完成了英雄名字.id.头像的下载并使用RecyclerView展示, 所以接下来就是点击每个英雄的caraview就能打开下一个活动进行英雄的介绍.先打开暴雪的官网查看有那些技能.故事.图片 ...

  7. 关于Java虚拟机运行时数据区域的总结

    Java虚拟机运行时数据区域 程序计数器(Program Counter) 程序计数器作为一个概念模型,这个是用来指示下一条需要执行的字节码指令在哪. Java的多线程实际上是通过线程轮转做到的,如果 ...

  8. 腾讯物联TencentOS tiny上云初探

    2017年中旬曾写过一篇关于物联网平台的文章<微软最完善,百度最“小气” 看微软阿里百度三大物联网云平台对比>.现在已经过去两年了,物联网的格局又发生了不少的变化.不过针对腾讯来说,其物联 ...

  9. C#.Net实现AutoCAD块属性提取

    https://blog.csdn.net/dengyiyu/article/details/2201175 本文主要给大家介绍一下SmartSoft中用C#.Net实现AutoCAD块属性提取的方法 ...

  10. Day 01--选题与设计(一)

    1.第一天我们主要确定了软件课设的项目,做一个学校内食堂订送餐的微信小程序.我们大体的设计思路是:可以实现学生身份的认证,幷使学生们能自行选择校园内的食堂,挑选各个食堂各个窗口菜谱上可以选择的菜,选择 ...