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遍历了整个关系图之后,每个人的管辖区间就确定下来了,然后就可以通过管辖区间来进行线段树区域覆盖和单点查询操作。
1 int cnt = 0; 2 void dfs(int n) 3 { 4 Start[n] = ++cnt; 5 int m = son[n].size(); 6 for(int i = 0; i < m; i++) 7 dfs(son[n][i]);//已经用vector son[n] 来存好了每个人的下属 8 End[n] = cnt; 9 }
1 #include<iostream> 2 #include<algorithm> 3 #include<vector> 4 #include<string> 5 #include<cstring> 6 #define lson l,m,rt<<1 7 #define rson m+1,r,rt<<1|1 8 using namespace std; 9 const int N = 50000+5; 10 vector<int> son[N]; 11 int Start[N], End[N]; 12 int tree[N<<2], lazy[N<<2]; 13 bool vis[N]; 14 int cnt = 0; 15 void dfs(int n) 16 { 17 Start[n] = ++cnt; 18 int m = son[n].size(); 19 for(int i = 0; i < m; i++) 20 dfs(son[n][i]); 21 End[n] = cnt; 22 } 23 void PushDown(int rt) 24 { 25 if(lazy[rt] != -1) 26 { 27 tree[rt<<1] = tree[rt<<1|1] = lazy[rt<<1|1] = lazy[rt<<1] = lazy[rt]; 28 lazy[rt] = -1; 29 } 30 } 31 void Revise(int L, int R, int C, int l, int r, int rt) 32 { 33 if(L <= l && r <= R) 34 { 35 lazy[rt] = tree[rt] = C; 36 return ; 37 } 38 PushDown(rt); 39 int m =l+r >> 1; 40 if(L <= m) Revise(L,R,C,lson); 41 if(m < R) Revise(L,R,C,rson); 42 } 43 int Query(int L, int l, int r, int rt) 44 { 45 if(l == r) 46 { 47 return tree[rt]; 48 } 49 int m = l+r >> 1; 50 PushDown(rt); 51 if(L <= m) return Query(L,lson); 52 else return Query(L,rson); 53 } 54 int main() 55 { 56 ios::sync_with_stdio(false); 57 cin.tie(0); 58 cout.tie(0); 59 int T; 60 cin >> T; 61 for(int i = 1; i <= T; i++) 62 { 63 cout << "Case #" << i << ":\n"; 64 int n, u, v; 65 cnt = 0; 66 cin >> n; 67 for(int i = 1; i <= n; i++) 68 son[i].clear(), vis[i] = 1; 69 for(int i = 1; i < n; i++) 70 { 71 cin >> u >> v; 72 son[v].push_back(u);//用vector去对应的关系 73 vis[u] = 0;//如果某个点成为过下属就标记一下 没有标记过的那个人就是Boss(最上级) 74 } 75 int pos = -1; 76 for(int i = 1; i <= n; i++) 77 if(vis[i]) 78 { 79 pos = i; 80 break; 81 } 82 dfs(pos);//从最上级的人开始递归, 找到每个人对应的区间 83 memset(tree, -1, sizeof(tree));//因为没有接到任务过的人查询的时候输出-1 84 memset(lazy, -1, sizeof(lazy));//所以直接memset为-1就好了,不需要再进行特判 85 int t; 86 cin >> t; 87 string str; 88 int x, y; 89 while(t--) 90 { 91 cin >> str; 92 if(str[0] == 'C') 93 { 94 cin >> x; 95 cout << Query(Start[x],1,cnt,1) << endl; 96 } 97 else 98 { 99 cin >> x >> y; 100 Revise(Start[x],End[x],y,1,cnt,1); 101 } 102 } 103 } 104 return 0; 105 }
转载于:https://www.cnblogs.com/MingSD/p/8386894.html
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 ...
- Assign the task HDU - 3974(线段树+dfs建树+单点查询+区间修改)
题意: 染色问题:给一个固定结构的树,现在有两个操作: (1) y 将结点x及其所有后代结点染成颜色y: (2)查询结点x当前的颜色. 其实就是区间染色问题,不过需要dfs预处理, 题目: There ...
- HDU - 3974 Assign the task (线段树 + dfs序)
HDU - 3974 题意:有个公司有一些关系,每个人(除了boss)都有且仅有一个上司,这就是一棵树的关系,然后会有一些操作,C i,询问第i个人现在的任务,T x y,把y任务给x, 给x相当于给 ...
- HDU 3974 Assign the task(树 并查集)
题意 公司中有n个员工 除了boss 每个员工都有自己的上司 自己下属的下属也是自己的下属 当给一个员工分配任务时 这个员工会把任务也分配到自己的所有下属 每个员工都只做最后一个被分配 ...
- 2016 Multi-University Training Contest 10 [HDU 5861] Road (线段树:区间覆盖+单点最大小)...
HDU 5861 题意 在n个村庄之间存在n-1段路,令某段路开放一天需要交纳wi的费用,但是每段路只能开放一次,一旦关闭将不再开放.现在给你接下来m天内的计划,在第i天,需要对村庄ai到村庄bi的道 ...
- HDU 3974 Assign the task(dfs时间戳+线段树成段更新)
题意:给定点的上下级关系,规定假设给i分配任务a.那么他的全部下属.都停下手上的工作,開始做a. 操作 T x y 分配x任务y,C x询问x的当前任务: Sample Input 1 5 4 3 3 ...
- 1631 小鲨鱼在51nod小学(线段树区间修改+单点查询:不用下传lazy的区间修改)
题目描述: 1631 小鲨鱼在51nod小学 鲨鱼巨巨2.0(以下简称小鲨鱼)以优异的成绩考入了51nod小学.并依靠算法方面的特长,在班里担任了许多职务. 每一个职务都有一个起始时间A和结束时间B, ...
- 树状数组之区间修改单点查询
树状数组的区间修改单点查询 树状数组其实本质还单点修改区间查询,但是我们怎么延伸到这个呢,我们建立一个差分数组, 比如: a[10]={4, 6, 7, 5, 1, 6, ...
- 树状数组相关应用之区间更新单点查询问题
区间更新单点查询 树状数组的基本应用是单点更新,区间查询(例如求区间和). 鉴于树状数组的空间复杂度和时间复杂度都比线段树小 而且代码也短 所以就有大神用强大的脑洞YY出了区间修改+单点查询的树状数组 ...
最新文章
- 【Spring】spring基于纯注解的声明式事务控制
- 电脑网络禁用了怎么恢复_网卡禁用怎么启用恢复
- 多线程的实现方式_Java中线程的状态及多线程的实现方式
- 最小二乘法(一元)推导
- Bootstrap创建拼接式按钮下拉菜单
- STM32F103:二.(2)串口控制LED
- keil5图标变成白色_【网上最简单】Chrome安装后打不开任何页面 amp; 改名后图标变成小白块[30秒解决]...
- FISCO BCOS 微众银行 WeDPR 隐私解决方案 资料汇总
- 二代测序 下载 NCBI sra 文件
- 【HTML5】初识前端页面结构与基本标签
- 【存储】HDS VSP
- Idea 设置Eclipse快捷键
- 使用注册表清理右键新建菜单
- 记录一次阿里云服务器被攻击事件
- html页面打印插件,分享8款网站开发中最好用的打印页面插件
- C++ fabs和abs区别
- 华硕主板更改UEFI安全启动项
- 190822——喜欢
- html5 选择金额样式,[JavaScript] 数字金额大写转换 v2
- kiwi syslog安装部署中的问题