hdu3974-Assign the task-(dfs+线段树)

题意:有n个人,有上下级关系,有m个操作,有两种操作1.把一个任务分给某个人,他的下属也会停下手中工作和他一起做;2.查询某个人的当前任务是什么?

解题:n-1个关系,总有一个人没有上级,以他为根节点用dfs搜索整张图可以得到一棵树,按“根左右”先序遍历,根表示自己,遍历到最右边的儿子结束,这段区间为自己的管辖范围,按遍历顺序构造一棵线段树,每个人记录管辖范围,一有任务分给某人,他就分散下去,线段树区间更新。

  1 #include<stdio.h>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<math.h>
  6 #include<string>
  7 #include<map>
  8 #include<queue>
  9 #include<stack>
 10 #include<set>
 11 #define ll long long
 12 #define inf 0x3f3f3f3f
 13 using namespace std;
 14 
 15 int T,n,v,u,cnt,m,x,y;
 16 char s[10];
 17 vector<int>son[50005];///儿子可能有多个,邻接表
 18 int dad[50005];///下标是儿子,内容是父亲
 19 int l[50005];
 20 int r[50005];///l和r两个数组之间的范围 表示 管辖的员工在线段树中的编号范围
 21 int tree[50005*4];
 22 int lazy[50005*4];
 23 
 24 void dfs(int now)///now是当前搜到的员工的编号
 25 {
 26     l[now]=++cnt;
 27     for(int i=0;i<son[now].size();i++)
 28     {
 29         int xx=son[now][i];
 30         dfs(xx);
 31     }
 32     r[now]=cnt;
 33 }
 34 
 35 void pushdown(int rt)
 36 {
 37     if( lazy[rt]!=-1 )
 38     {
 39         tree[ rt*2 ] = tree[ rt*2+1 ] = lazy[ rt*2 ] = lazy[ rt*2+1 ] =lazy[rt];
 40         lazy[rt]=-1;///懒标记赋值给儿子后清空为-1
 41     }
 42 }
 43 
 44 
 45 void build(int l,int r,int rt)
 46 {
 47     if(l==r)
 48     {
 49         tree[rt]=-1;
 50         return;
 51     }
 52     int mid=(l+r)/2;
 53     build(l,mid,rt*2);
 54     build(mid+1,r,rt*2+1);///不需要求和
 55 }
 56 
 57 void update(int L,int R,int p,int l,int r,int rt)
 58 {
 59     if( L<=l && r<=R )
 60     {
 61         tree[rt]=lazy[rt]=p;
 62         return;
 63     }
 64     int mid=(l+r)/2;
 65     pushdown(rt);
 66     if( L<=mid )
 67         update(L,R,p,l,mid,rt*2);
 68     if( mid+1<=R )
 69         update(L,R,p,mid+1,r,rt*2+1);
 70 }
 71 
 72 int query(int l,int r,int rt,int x)
 73 {
 74     if( l==r )
 75         return tree[rt];
 76     int mid=(l+r)/2;
 77     pushdown(rt);
 78     if(x<=mid)
 79         return query(l,mid,rt*2,x);
 80     else
 81         return query(mid+1,r,rt*2+1,x);
 82 }
 83 
 84 int main()
 85 {
 86 
 87     scanf("%d",&T);
 88     for(int t=1;t<=T;t++)
 89     {
 90         memset(dad,0,sizeof(dad));
 91         memset(lazy,-1,sizeof(lazy));
 92         memset(tree,-1,sizeof(tree));
 93         for(int i=1;i<=n;i++)
 94             son[i].clear();
 95 
 96         scanf("%d",&n);
 97         for(int i=1;i<n;i++)
 98         {
 99             scanf("%d%d",&u,&v);///v是u的父亲
100             dad[u]=v;
101             son[v].push_back(u);
102         }
103 
104         for(int i=1;i<=n;i++)
105         {
106             if( dad[i]==0 )///没有父亲,便是祖宗
107             {
108                 v=i;
109                 break;
110             }
111         }
112         cnt=0;
113         dfs(v);///从祖宗开始往下搜
114 
115         printf("Case #%d:\n",t);
116         scanf("%d",&m);
117         while(m--)
118         {
119             string ss;
120             cin>>ss;
121             if( ss[0]=='C' )///查询a的任务
122             {
123                 scanf("%d",&x);
124                 int ans=query(1,cnt,1,l[x]);
125                     printf("%d\n",ans);
126             }
127             else
128             {
129                 scanf("%d%d",&x,&y);///让员工a做任务b,a会叫他的下属一起做,左右区间表示需要做的人,包括自己
130                 update( l[x],r[x],y,1,cnt,1 );
131             }
132         }
133 
134     }
135     return 0;
136 }

 

posted @ 2019-07-20 23:04  守林鸟  阅读(152)  评论(0编辑  收藏  举报