HDU - 3974 Assign the task (DFS建树+区间覆盖+单点查询)
题意:一共有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建树+区间覆盖+单点查询)的更多相关文章
- 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 ...
- HDU 3974 Assign the task(dfs建树+线段树)
题目大意:公司里有一些员工及对应的上级,给出一些员工的关系,分配给某员工任务后,其和其所有下属都会进行这项任务.输入T表示分配新的任务, 输入C表示查询某员工的任务.本题的难度在于建树,一开始百思不得 ...
- HDU 3974 Assign the task (DFS序 + 线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3974 给你T组数据,n个节点,n-1对关系,右边的是左边的父节点,所有的值初始化为-1,然后给你q个操 ...
- HDU 3974 Assign the task (DFS+线段树)
题意:给定一棵树的公司职员管理图,有两种操作, 第一种是 T x y,把 x 及员工都变成 y, 第二种是 C x 询问 x 当前的数. 析:先把该树用dfs遍历,形成一个序列,然后再用线段树进行维护 ...
- HDU.1556 Color the ball (线段树 区间更新 单点查询)
HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...
- HDU 3974 Assign the task
Assign the task Problem Description There is a company that has N employees(numbered from 1 to N),ev ...
- hdu 3974 Assign the task(dfs序上线段树)
Problem Description There is a company that has N employees(numbered from 1 to N),every employee in ...
- HDU 3974 Assign the task 并查集/图论/线段树
Assign the task Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?p ...
- HDU 3974 Assign the task(简单线段树)
Assign the task Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
随机推荐
- Xcode 常用
常用快捷键: 1. 运行程序 command + R 2. Clean command + shift + K 3. 模拟器上没 Home 键? command + shift + H 4. h 文件 ...
- Redis总结(八)如何搭建高可用的Redis集群
以前总结Redis 的一些基本的安装和使用,大家可以这这里查看Redis 系列文章:https://www.cnblogs.com/zhangweizhong/category/771056.html ...
- 前端笔记之微信小程序(四)WebSocket&Socket.io&摇一摇案例&地图|地理位置
一.WebSocket概述 http://www.ruanyifeng.com/blog/2017/05/websocket.html Workerman一款开源高性能异步PHP socket即时通讯 ...
- scrapy框架与python爬虫
- 并发编程(4)——AbstractQueuedSynchronizer
AQS 内部类Node 等待队列是CLH有锁队列的变体. waitStatus的几种状态: static final int CANCELLED = 1; /** waitStatus value t ...
- Vue系列:Websocket 使用配置
WebSocket 是什么? WebSocket 是一种网络通信协议.而且是在 HTML5 才开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. 为什么需要 WebSocket ? 了解计算 ...
- 【0725 | Day 1】计算机编程/计算机组成原理/计算机操作系统
什么是编程 编程语言:人与计算机交流的手段 编程:通过编程语言编写文件 学习编程的目的:让计算机代替人力,为我们服务 计算机组成原理 计算机由五大部分组成:控制器.运算器.存储器.输入设备.输出设备. ...
- C++实现多组数据合并输出
思路 假设有多组数据,每一组都是按从小到大的顺序输入的,设计如下数据结构 前面一列是每一组数据的首部,后面是真正的数据,首部的定义为: struct head { Node* next; head* ...
- windows下通过idea连接hadoop和spark集群
###windows下链接hadoop集群 1.假如在linux机器上已经搭建好hadoop集群 2.在windows上把hadoop的压缩包解压到一个没有空格的目录下,比如是D盘根目录 3.配置环境 ...
- 《统计学习方法》极简笔记P2:感知机数学推导
感知机模型 输入空间是$\chi\subseteq\mathbb{R}^n$,输出空间是$y={+1,-1}$ 感知机定义为:$f(x)=sign(wx+b)$ 感知机学习策略 输入空间任一点$x_0 ...