Assign the task-HDU3974 dfs序+线段树
题意:
一个公司有n个员工,每个员工都有一个上司,一个人下属的下属也是这个人的下属,因此可将他们的关系看成一棵树,
然后给定两种操作,C操作是查询当前员工的工作,T操作是将y工作分配给x员工,当一个人得到y工作时,他的
员工也会得到这个工作,即这个点和他的子树的工作都变成y。
链接: http://acm.hdu.edu.cn/showproblem.php?pid=3974
思路:
先一遍dfs求出该员工掌管的员工区间,每次修改时用线段树修改这个区间的员工即可,而查询时只要查询l_[x](该员工在dfs序下的编号)即可
代码:
#include <bits/stdc++.h> #define ls node<<1,l,mid #define rs node<<1|1,mid+1,r using namespace std; const int MAXN=5e4+4; typedef long long ll; int n;int l_[MAXN],r_[MAXN],f[MAXN]; int tree[MAXN<<2]; vector<int>v[MAXN]; int cnt; void dfs(int now) { l_[now]=++cnt; for(int i=0;i<v[now].size();i++) { dfs(v[now][i]); } r_[now]=cnt; } void build(int node,int l,int r) { tree[node]=-1; if(l==r) return; int mid=(l+r)>>1; build(ls); build(rs); } void push_down(int node) { if(tree[node]!=-1)//员工的任务等于上司的任务 { tree[node<<1]=tree[node]; tree[node<<1|1]=tree[node]; tree[node]=-1; } } void update(int node,int l,int r,int x,int y,int k) { if(x<=l&&y>=r) { tree[node]=k; return; } push_down(node); int mid=(l+r)>>1; if(x<=mid) update(ls,x,y,k); if(y>mid) update(rs,x,y,k); } int query(int node,int l,int r,int i) { if(l==r) { return tree[node]; } push_down(node); int mid=(l+r)>>1; if(i<=mid) return query(ls,i); else return query(rs,i); } void init() { cnt=0; memset(f,0,sizeof(f)); for(int i=1;i<=n;i++) v[i].clear(); } int main() { int t;scanf("%d",&t);int case_=0; while(t--) { printf("Case #%d:\n",++case_); scanf("%d",&n); init(); //初始化 for(int i=1;i<=n-1;i++) { int x,y; scanf("%d%d",&x,&y); v[y].push_back(x); f[x]=y; } for(int i=1;i<=n;i++)//获得dfs序 { if(!f[i]) dfs(i); } build(1,1,cnt); int q;scanf("%d",&q); while(q--) { char str[10];int x,y; scanf("%s",str); if(str[0]=='T') { scanf("%d%d",&x,&y); update(1,1,cnt,l_[x],r_[x],y); } else { scanf("%d",&x); printf("%d\n",query(1,1,cnt,l_[x])); } } } return 0; }