线段树+dfs序(Apple Tree )(Assign the task )

线段树+dfs序

给定一棵n个节点的树,m次查询,每次查询需要求出某个节点深度为h的所有子节点。

作为预处理,首先将树的所有节点按深度保存起来,每个深度的所有节点用一个线性结构保存,每个深度的节点相对顺序要和前序遍历一致。

然后从树的根节点进行dfs,对于每个节点记录两个信息,一个是dfs进入该节点的时间戳in[id],另一个是dfs离开该节点的时间戳out[id]。

最后对于每次查询,求节点v在深度h的所有子节点,只需将深度为h并且dfs进入时间戳在in[v]和out[v]之间的所有节点都求出来即可。

Step 1:

如下图,可以看到,由于普通的树并不具有区间的性质,所以在考虑使用线段树作为解题思路时,需要对给定的数据进行转化,首先对这棵树进行一次dfs遍历,记录dfs序下每个点访问起始时间与结束时间,记录起始时间是前序遍历,结束时间是后序遍历,同时对这课树进行重标号。

Step 2:

如下图,DFS之后,那么树的每个节点就具有了区间的性质。

那么此时,每个节点对应了一个区间,而且可以看到,每个节点对应的区间正好“管辖”了它子树所有节点的区间,那么对点或子树的操作就转化为了对区间的操作。

例题一:

POJ-3321  Apple Tree

 

There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been carefully nurturing the big apple tree.

The tree has N forks which are connected by branches. Kaka numbers the forks by 1 to N and the root is always numbered by 1. Apples will grow on the forks and two apple won't grow on the same fork. kaka wants to know how many apples are there in a sub-tree, for his study of the produce ability of the apple tree.

The trouble is that a new apple may grow on an empty fork some time and kaka may pick an apple from the tree for his dessert. Can you help kaka?

 

 

Input

The first line contains an integer N (N ≤ 100,000) , which is the number of the forks in the tree.
The following N - 1 lines each contain two integers u and v, which means fork u and fork v are connected by a branch.
The next line contains an integer M (M ≤ 100,000).
The following M lines each contain a message which is either
"x" which means the existence of the apple on fork x has been changed. i.e. if there is an apple on the fork, then Kaka pick it; otherwise a new apple has grown on the empty fork.
or
"x" which means an inquiry for the number of apples in the sub-tree above the fork x, including the apple (if exists) on the fork x
Note the tree is full of apples at the beginning

Output

For every inquiry, output the correspond answer per line.

Sample Input

3
1 2
1 3
3
Q 1
C 2
Q 1

Sample Output

3
2
题目大意: 
一棵树上长了苹果,每一个树枝节点上有长苹果和不长苹果两种状态,两种操作,一种操作能够改变树枝上苹果的状态,另一种操作询问某一树枝节点一下的所有的苹果有多少。操作C:如果有苹果,则经过C操作变成没有,如果没有苹果,经过C操作变成有。
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int maxn=100010;
  7 struct node{
  8     int to;
  9     int nex;
 10 }e[maxn<<2];
 11 int head[maxn<<2],v[maxn<<2],u[maxn<<2];
 12 int vis[maxn<<2],cnt,num;
 13 struct tree{
 14     int l;
 15     int r;
 16     int sum;
 17 }tree[maxn<<2];
 18 void init()
 19 {
 20     memset(vis,0,sizeof(vis));
 21     memset(head,-1,sizeof(head));
 22     cnt=0;
 23 }
 24 void dfs(int x)
 25 {
 26     ++num;
 27     v[x]=num;
 28     vis[x]=1;
 29     for(int i=head[x];i!=-1;i=e[i].nex)
 30     {
 31         int t=e[i].to;
 32         if(vis[t]==1)
 33             continue;
 34         dfs(t);
 35     }
 36     u[x]=num;
 37 }
 38 void add(int x,int y)
 39 {
 40     e[cnt].to=y;
 41     e[cnt].nex=head[x];
 42     head[x]=cnt++;
 43 }
 44 void pushup(int cur)
 45 {
 46     tree[cur].sum=tree[cur<<1].sum+tree[cur<<1|1].sum;
 47 }
 48 void build(int l,int r,int cur)
 49 {
 50     tree[cur].l=l;
 51     tree[cur].r=r;
 52     if(l==r)
 53     {
 54         tree[cur].sum=1;
 55         return;
 56     }
 57     int mid=(l+r)/2;
 58     build(l,mid,cur<<1);
 59     build(mid+1,r,cur<<1|1);
 60     pushup(cur);
 61 }
 62 void update(int val,int cur)
 63 {
 64     if(tree[cur].l==tree[cur].r)
 65     {
 66         if(tree[cur].sum==0)
 67         {
 68             tree[cur].sum=1;
 69             return;
 70         }
 71         else
 72         {
 73             tree[cur].sum=0;
 74             return;
 75         }
 76     } 
 77     int mid=(tree[cur].l+tree[cur].r)/2;
 78     if(val<=mid)
 79         update(val,cur<<1);
 80     if(val>=mid+1)
 81         update(val,cur<<1|1);
 82     pushup(cur);
 83 }
 84 int query(int pl,int pr,int cur)
 85 {
 86     if(pl<=tree[cur].l&&tree[cur].r<=pr)
 87     {
 88         return tree[cur].sum;
 89     }
 90     int ans=0;
 91     int mid=(tree[cur].l+tree[cur].r)/2;
 92     if(pl<=mid)
 93         ans+=query(pl,pr,cur<<1);
 94     if(pr>=mid+1)
 95         ans+=query(pl,pr,cur<<1|1);
 96     return ans;
 97 }
 98 int main()
 99 {
100     int n,m;
101     int a,b;
102     while(~scanf("%d",&n)&&n)
103     {
104         init();
105         num=0;
106         for(int i=1;i<=n-1;i++)
107         {
108             scanf("%d%d",&a,&b);
109             add(a,b);
110         }
111         dfs(1);
112         char s[5];
113         build(1,n,1);
114         scanf("%d",&m);
115         while(m--)
116         {
117             scanf("%s%d",s,&a);
118             if(s[0]=='C')
119             {
120                 update(v[a],1);
121             }
122             if(s[0]=='Q')
123             {
124                 printf("%d\n",query(v[a],u[a],1));
125             } 
126         } 
127     }
128 }

HDU-3974   Assign the task

There is a company that has N employees(numbered from 1 to N),every employee in the company has a immediate boss (except for the leader of whole company).If you are the immediate boss of someone,that person is your subordinate, and all his subordinates are your subordinates as well. If you are nobody's boss, then you have no subordinates,the employee who has no immediate boss is the leader of whole company.So it means the N employees form a tree. 

The company usually assigns some tasks to some employees to finish.When a task is assigned to someone,He/She will assigned it to all his/her subordinates.In other words,the person and all his/her subordinates received a task in the same time. Furthermore,whenever a employee received a task,he/she will stop the current task(if he/she has) and start the new one. 

Write a program that will help in figuring out some employee’s current task after the company assign some tasks to some employee.

InputThe first line contains a single positive integer T( T <= 10 ), indicates the number of test cases. 

For each test case: 

The first line contains an integer N (N ≤ 50,000) , which is the number of the employees. 

The following N - 1 lines each contain two integers u and v, which means the employee v is the immediate boss of employee u(1<=u,v<=N). 

The next line contains an integer M (M ≤ 50,000). 

The following M lines each contain a message which is either 

"C x" which means an inquiry for the current task of employee x 

or 

"T x y"which means the company assign task y to employee x. 

(1<=x<=N,0<=y<=10^9)OutputFor each test case, print the test case number (beginning with 1) in the first line and then for every inquiry, output the correspond answer per line.Sample Input

1 
5 
4 3 
3 2 
1 3 
5 2 
5 
C 3 
T 2 1
C 3 
T 3 2 
C 3

Sample Output

Case #1:
-1 
1 
2
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int maxn=50010;
  7 struct node{
  8     int to;
  9     int nex;
 10 }e[maxn<<2];
 11 int head[maxn<<2],v[maxn<<2],u[maxn<<2];
 12 int vis[maxn<<2],cnt,num,in[maxn<<2];
 13 struct tree{
 14     int l;
 15     int r;
 16     int sum;
 17     int laz;
 18 }tree[maxn<<3];
 19 void init()
 20 {
 21     memset(tree,0,sizeof(tree));
 22     memset(e,0,sizeof(e));
 23     memset(v,0,sizeof(v));
 24     memset(u,0,sizeof(u));
 25     memset(in,0,sizeof(in));
 26     memset(vis,0,sizeof(vis));
 27     memset(head,-1,sizeof(head));
 28     cnt=0;
 29 }
 30 void dfs(int x)
 31 {
 32     ++num;
 33     v[x]=num;
 34     vis[x]=1;
 35     for(int i=head[x];i!=-1;i=e[i].nex)
 36     {
 37         int t=e[i].to;
 38         if(vis[t]==1)
 39             continue;
 40         dfs(t);
 41     }
 42     u[x]=num;
 43 }
 44 void add(int x,int y)
 45 {
 46     e[cnt].to=y;
 47     e[cnt].nex=head[x];
 48     head[x]=cnt++;
 49 }
 50 void pushdown(int cur)
 51 {
 52     if(tree[cur].laz!=0)
 53     {
 54         tree[cur<<1].laz=tree[cur<<1|1].laz=tree[cur].laz;
 55         tree[cur<<1].sum=tree[cur<<1|1].sum=tree[cur].laz;
 56         tree[cur].laz=0;
 57     }
 58     return;
 59 }
 60 
 61 void build(int l,int r,int cur)
 62 {
 63     tree[cur].l=l;
 64     tree[cur].r=r;
 65     tree[cur].laz=0;
 66     tree[cur].sum=0;
 67     if(l==r)
 68     {
 69         return;
 70     }
 71     int mid=(l+r)/2;
 72     build(l,mid,cur<<1);
 73     build(mid+1,r,cur<<1|1);
 74 }
 75 void update(int pl,int pr,int num,int cur)
 76 {
 77     if(pl<=tree[cur].l&&tree[cur].r<=pr)
 78     {
 79         tree[cur].laz=num;
 80         tree[cur].sum=num;
 81         return;
 82     }
 83     pushdown(cur);
 84     int mid=(tree[cur].l+tree[cur].r)/2;
 85     if(pl<=mid)
 86         update(pl,pr,num,cur<<1);
 87     if(pr>=mid+1)
 88         update(pl,pr,num,cur<<1|1);
 89 }
 90 int query(int pl,int pr,int cur)//一定要注意query中不能缺少pushdown
 91 {
 92     if(pl<=tree[cur].l&&tree[cur].r<=pr)
 93     {
 94         return tree[cur].sum;
 95     }
 96     //int ans=0;
 97     pushdown(cur);
 98     int mid=(tree[cur].l+tree[cur].r)/2;
 99     if(pl<=mid)
100         return query(pl,pr,cur<<1);
101     if(pr>=mid+1)
102         return query(pl,pr,cur<<1|1);
103 }
104 int main()
105 {
106     int T;
107     int n,m;
108     int a,b;
109     cin>>T;
110     int id=1;
111     while(T--)
112     {
113         num=0;
114         init();
115         scanf("%d",&n);
116         for(int i=1;i<=n-1;i++)
117         {
118             scanf("%d%d",&a,&b);
119             add(b,a);
120             in[a]++;
121         } 
122         for(int i=1;i<=n;i++)
123         {
124             if(in[i]==0)
125             {
126                 dfs(i);
127                 break;
128             }
129         }
130         char s[5];
131         build(1,n,1);printf("Case #%d:\n",id++);
132         scanf("%d",&m);
133         while(m--)
134         {
135             scanf("%s",s);
136             if(s[0]=='C')
137             {
138                 scanf("%d",&a);
139                 int ans=query(v[a],u[a],1);
140                 if(ans==0)
141                 printf("-1\n");
142                 else
143                 printf("%d\n",ans); 
144             }
145             if(s[0]=='T')
146             {
147                 scanf("%d%d",&a,&b);
148                 update(v[a],u[a],b,1);
149             } 
150         }
151     }
152 }

 参考博客:

https://blog.csdn.net/qq_24489717/article/details/50569644

posted @ 2018-08-09 18:44  *starry*  阅读(289)  评论(0编辑  收藏  举报