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 }