题目大意

t 组数据(t<=10),每组第一行一个 n 表示 n 个员工(n<=5e4),接下来 n-1 行,每行两个整数 u,v 表示 v 是 u 的上司

然后一行 m 表示有 m 个操作(m<=5e4) , 接下来 m 行 由一个字符 和 整型数构成 ,表示不同操作

C x 表示 输出 第 x 个员工的工作号

T x y 表示 将 第 x 个员工的工作号变为 y (x<=n,0<=y<=1e9)

规定,改变工作时,被改变员工的下属一同变为 y

解析

通读题干,发现直接给了个多叉树,于是法一我们先讲直接模拟

法一:直接模拟多叉树

首先,读者可以画个树,自行标号dfs序,体会下dfs序的特点

不难发现,对于任意子树所含的结点编号是连续的

且该子树所含结点最小编号就是根结点编号

然后这个dfs序就是我们解决这道题的关键所在

按题意直接建好多叉树,标好dfs序,然后你会发现其实操作蛮简单的

查询员工,变成一层层去找对应子树根结点

更改员工,找到对应子树根结点挂上lazy就完事了

相当简单,不多说了,直接挂代码了

#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
struct node
{int l,r,job,lazy;vector<int> son;
}tree[50005];
int t,n,m,cnt,root,u,v,x,y;
char c;
bool notroot[50005];
void dfsbuild(int rt)
{tree[rt].job=tree[rt].lazy=-1;tree[rt].l=++cnt;for(auto x:tree[rt].son) dfsbuild(x);tree[rt].r=cnt;
}
void down(int rt)
{if(tree[rt].lazy==-1) return;for(auto s:tree[rt].son) tree[s].job=tree[s].lazy=tree[rt].lazy;tree[rt].lazy=-1;
}
void update(int x,int y,int rt)
{if(x==rt){tree[rt].job=tree[rt].lazy=y;return;}down(rt);for(auto s:tree[rt].son) if(tree[s].l<=tree[x].l&&tree[x].l<=tree[s].r) update(x,y,s);
}
int query(int x,int rt)
{if(x==rt) return tree[rt].job;down(rt);for(auto s:tree[rt].son) if(tree[s].l<=tree[x].l&&tree[x].l<=tree[s].r) return query(x,s);
}
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>t;for(int cas=1;cas<=t;cas++){cin>>n,cnt=0;for(int i=1;i<=n;i++) tree[i].son.clear(),notroot[i]=0;for(int i=1;i<n;i++) cin>>u>>v,tree[v].son.push_back(u),notroot[u]=1;for(int i=1;i<=n;i++) if(!notroot[i]) root=i;dfsbuild(root);cin>>m;cout<<"Case #"<<cas<<":"<<endl;while(m--){cin>>c>>x;if(c=='C') cout<<query(x,root)<<endl;else cin>>y,update(x,y,root);}}return 0;
}

法二:线段树

其实这个题线段树和多叉树做起来还蛮像的,但是其实截然不同,操作也很不相同

然后dfs序还是本题关键

首先打好dfs序,原多叉树每个子树的根结点就会对应一段区间(最小编号到最大编号)

然后把多叉树直接扔掉不要管了,直接处理得到的区间(就像是把多叉树直接拍扁成一个区间)

你就会发现,什么多叉树,就是个变相考你区间染色,和多叉树直接没了关系

查询一个点,就是查其单点编号

更改一个点,就是改一段对应区间

线段树和之前的树没啥关系,只是为了实现区间操作的功能而建立的,不要混乱了

其实这个方法只要理清思路不混乱就没啥了,直接上代码了

#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
int t,n,m,tree[50005<<2],lid[50005],rid[50005],cnt,u,v,x,y;
bool notroot[50005];
char c;
vector<int> g[50005];
void initbuild(int l,int r,int rt)
{tree[rt]=-1;if(l==r) return;initbuild(l,(l+r)/2,rt<<1);initbuild((l+r)/2+1,r,rt<<1|1);
}
void dfs(int rt)
{lid[rt]=++cnt;for(auto s:g[rt]) dfs(s);rid[rt]=cnt;
}
void down(int rt)
{if(tree[rt]==-1) return;tree[rt<<1]=tree[rt<<1|1]=tree[rt];tree[rt]=-1;
}
void update(int a,int b,int c,int l,int r,int rt)
{if(r<a||l>b) return;if(a<=l&&r<=b){tree[rt]=c;return;}down(rt);update(a,b,c,l,(l+r)/2,rt<<1);update(a,b,c,(l+r)/2+1,r,rt<<1|1);
}
int query(int x,int l,int r,int rt)
{if(l==r) return tree[rt];down(rt);if(x<=(l+r)/2) return query(x,l,(l+r)/2,rt<<1);return query(x,(l+r)/2+1,r,rt<<1|1);
}
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>t;for(int cas=1;cas<=t;cas++){cin>>n,cnt=0;initbuild(1,n,1);for(int i=1;i<=n;i++) g[i].clear(),notroot[i]=0;for(int i=1;i<n;i++) cin>>u>>v,g[v].push_back(u),notroot[u]=1;for(int i=1;i<=n;i++) if(!notroot[i]) dfs(i);cin>>m;cout<<"Case #"<<cas<<":"<<endl;while(m--){cin>>c>>x;if(c=='C') cout<<query(lid[x],1,n,1)<<endl;else cin>>y,update(lid[x],rid[x],y,1,n,1);}}return 0;
}

法三:并查集

说来惭愧,这个方法我实在没法起名

说他是并查集吧,其实并查集的find union操作都没用上

形式上似乎是并查集,但并没有使用任何并查集的功能,应该说和并查集半点关系没有吧

实在不知道该怎么说,算了,不管这个了

总之这个方法就是直接做,也算不上模拟什么的,反正就是直接从逻辑角度就把答案推出来了,非常巧妙

记录每个结点分到的工作与时间,并且不向下更新

查询的时候一路找爸爸就可以了,时间最靠后的那个任务就是当前儿子的任务

思路过于简单了,不多说废话了

#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
struct node
{int job,time;
}a[50005];
int fa[50005],t,n,m,u,v,x,y,cnt,tmp;
char c;
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>t;for(int cas=1;cas<=t;cas++){cin>>n,cnt=0;for(int i=1;i<=n;i++) fa[i]=a[i].job=a[i].time=-1;for(int i=1;i<n;i++) cin>>u>>v,fa[u]=v;cin>>m;cout<<"Case #"<<cas<<":"<<endl;while(m--){cin>>c>>x;if(c=='C'){y=a[x].job;tmp=a[x].time;while(x!=-1) {if(a[x].time>tmp) y=a[x].job,tmp=a[x].time;x=fa[x];}cout<<y<<endl;}else cin>>y,a[x].job=y,a[x].time=++cnt;}}return 0;
}

这个方法是我看了别人的题解后写的

然后我就在想,哇,这么简单我怎么没想到呢

然后我发现不对劲,我怎么可能没想到?

这不是最坏情况O(mn)会超时的吗。。当时肯定直接pass掉了啊。。

为啥就能A掉了,果然数据比较弱,没有那种链的情况。。

真滴服。。

不得不说暴力大法好。。。

如果比赛遇到这种情况就爽死了QAQ,所以说如果一道题做不出来,偶尔暴力赌一把也挺好的。。。

HDU-3974 Assign the task 线段树 或 直接模拟多叉树 或 并查集 (三种方法)相关推荐

  1. HDU - 3974 Assign the task (线段树 + dfs序)

    HDU - 3974 题意:有个公司有一些关系,每个人(除了boss)都有且仅有一个上司,这就是一棵树的关系,然后会有一些操作,C i,询问第i个人现在的任务,T x y,把y任务给x, 给x相当于给 ...

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

  3. HDU 3974 Assign the task(树 并查集)

    题意  公司中有n个员工  除了boss  每个员工都有自己的上司  自己下属的下属也是自己的下属  当给一个员工分配任务时  这个员工会把任务也分配到自己的所有下属   每个员工都只做最后一个被分配 ...

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

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

  5. HDU 3974 Assign the task(dfs时间戳+线段树成段更新)

    题意:给定点的上下级关系,规定假设给i分配任务a.那么他的全部下属.都停下手上的工作,開始做a. 操作 T x y 分配x任务y,C x询问x的当前任务: Sample Input 1 5 4 3 3 ...

  6. hdu dfs入门java_hdu1181变形课dfs/bfs/并查集三种解法(java)

    题目链接 Problem Description 呃-变形课上Harry碰到了一点小麻烦,因为他并不像Hermione那样能够记住所有的咒语而随意的将一个棒球变成刺猬什么的,但是他发现了变形咒语的一个 ...

  7. HDU 1166 敌兵布阵(线段树:点更新,区间求和)

    HDU 1166 敌兵布阵(线段树:点更新,区间求和) http://acm.hdu.edu.cn/showproblem.php?pid=1166 题意: 给你n个整数,然后给你多条命令,每条命令如 ...

  8. HDU 3016 Man Down (线段树+dp)

    HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  9. 2019CCPC网络赛 1002 HDU 6703(权值线段树)

    2019CCPC网络赛 1002 HDU 6703(权值线段树) 思路:用权值线段树存题目给的数据后,2操作就是求权值线段树中大于等于k的部分中,靠近左端点的第一个大于r的值(这个求出来的只是原序列中 ...

最新文章

  1. 刘锋:互联网左右大脑结构与钱学森开放复杂巨系统
  2. WCF分发简述-ChannelDispatcher,EndpointDispatcher,MessageFilter
  3. C语言 函数的封装示例(允许存在同名但形参不同函数)
  4. 干货|EOS和它引领的POS新时代
  5. BZOJ 4514 费用流
  6. 在WebApi中实现Cors访问
  7. Python装饰器的实现原理
  8. python模拟登陆 验证码el_8-python模拟登入(无验证码)
  9. 不想跑滴滴,如何利用汽车赚钱?
  10. 【汇编语言与计算机系统结构笔记16】子程序设计:子程序的嵌套与递归,多个模块之间的参数传送
  11. CAN分析仪创芯科技使用(Ubuntu)
  12. 安卓psp模拟器联机教程_谁知道手机版的ppsspp模拟器怎么联机啊?
  13. 极光推送在Android端的集成
  14. busybox v1.22.1(debian 1:1.22.0-19) built-in shell(ash)解决方案
  15. html四张图片拼图,js实现html滑动图片拼图验证
  16. HTML学习第十二章------布局和排版
  17. JS---Cookies完整介紹 申精!
  18. 计算机协会财务部部长职责,社团财务部部长职责.doc
  19. java基础入门篇(1)
  20. 销售宝:ERP软件系统对于企业有什么帮助?

热门文章

  1. Java内存溢出异常(下)
  2. Luogu P1039 侦探推理(模拟+枚举)
  3. 201521123050 《Java程序设计》第13周学习总结
  4. request.getAttribute()和request.getParameter()区别
  5. slf4j使用(二)
  6. asp.net关于页面不回发,不生成__doPostBack方法问题的完美解决方案--ZT
  7. UVA-10817- Headmaster's Headache(状压DP)
  8. validatebox自定义验证规则以及使用
  9. easyUI 如何不跳转页面,只是加载替换center部分内容
  10. iOS Crash文件的解析(一)