百度之星2014复赛 - 1002 - The Query on the Tree

先上题目:

The Query on the Tree

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 54    Accepted Submission(s): 18


Problem Description
  度度熊最近沉迷在和树有关的游戏了,他一直认为树是最神奇的数据结构。一天他遇到这样一个问题:
  有一棵树,树的每个点有点权,每次有三种操作:
  1. Query x 表示查询以x为根的子树的权值和。
  2. Change x y 表示把x点的权值改为y(0<=y<=100)。
  3. Root x 表示把x变为根。
  现在度度熊想请更聪明的你帮助解决这个问题。
 

 

Input
  第一行为数据组数T(1 <= T <= 100)
  每组数据第一行为N(1<= N <= 10000),表示树的节点数。
  后面N-1行每行有两个数x,y ,表示x,y之间有一条边 1<=x,y<=N。初始时树是以1号节点为根节点。
  之后的一行为N个数表示这N个点的点权(点权的范围是0到100)。
  然后为整数Q(Q<=1000)为操作次数。
  之后的Q行为描述中的三种操作。
 

 

Output
  对于第k组输入数据,第一行输出Case #k 接下来对于每个”Query x”操作,输出以x为根的子数和。
 

 

Sample Input
2
5
1 2
1 3
3 4
3 5
1 2 3 4 5 5
Query 1
Change 3 10
Query 1
Root 4
Query 3
8
1 2
1 3
3 4
4 5
5 6
5 7
4 8
1 2 3 4 5 6 7 8
5
Query 1
Query 3
Root 5
Query 3
Query 1
 

 

Sample Output
Case #1:
15
22
18
Case #2:
36
33
6
3
 

 

Source
 

  中文题意不解释,思路记录每一个节点的当前父节点(根节点的父节点可记为0) ,然后对于三种操作,如果是修改某个结点的值,那就修改完这个值以及当前节点的子树的值以后,向父节点方向修改每一个节点的子树的值;如果是修改根节点,那就从新根节点开始向父节点方向移动,将遇到的节点的父节点都改成向新根节点方向,同时更新子树的最值;如果是查询的话,就直接输出。需要注意的是既的更新父节点以及子树的权值。

 

上代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <utility>
 4 #define MAX 10002
 5 using namespace std;
 6 typedef pair<int,int> pii;
 7 
 8 int n,tot;
 9 int p[MAX];
10 int fa[MAX];
11 int w[MAX];
12 int s[MAX];
13 pii e[MAX<<1];
14 char q[10];
15 bool f;
16 
17 void reset(){
18     memset(p,-1,sizeof(int)*(n+1));
19     tot=0;
20 }
21 
22 void add(int u,int v){
23     e[tot].first=v; e[tot].second=p[u]; p[u]=tot++;
24     e[tot].first=u; e[tot].second=p[v]; p[v]=tot++;
25 }
26 
27 int deal(int u,int t){
28     int c=0;
29     s[u]=0;
30     fa[u]=t;
31     for(int v=p[u];v!=-1;v=e[v].second){
32         if(e[v].first!=t){
33             c = deal(e[v].first,u);
34             s[u]+=c;
35         }
36     }
37     s[u]+=w[u];
38     return s[u];
39 }
40 
41 void C(int a,int v){
42     int c = w[a];
43     while(a!=0){
44         s[a] = s[a] - c + v;
45         a = fa[a];
46     }
47 }
48 
49 void R(int r,int t){
50     s[r]=0;
51     for(int i=p[r];i!=-1;i=e[i].second){
52         if(e[i].first==t) continue;
53         if(e[i].first==fa[r]) R(fa[r],r);
54         s[r]+=s[e[i].first];
55         fa[e[i].first]=r;
56     }
57     s[r]+=w[r];
58 }
59 
60 int main()
61 {
62     int t,u,v,a,m;
63     //freopen("data.txt","r",stdin);
64     scanf("%d",&t);
65     for(int z=1;z<=t;z++){
66         printf("Case #%d:\n",z);
67         scanf("%d",&n);
68         reset();
69         for(int i=1;i<n;i++){
70             scanf("%d %d",&u,&v);
71             add(u,v);
72         }
73         for(int i=1;i<=n;i++) scanf("%d",&w[i]);
74         deal(1,0);
75         scanf("%d",&a);
76         while(a--){
77             scanf("%s %d",q,&m);
78             if(q[0]=='Q'){
79                 printf("%d\n",s[m]);
80             }else if(q[0]=='C'){
81                 scanf("%d",&v);
82                 C(m,v);
83                 w[m]=v;
84             }else{
85                 R(m,0);
86                 fa[m]=0;
87             }
88         }
89     }
90     return 0;
91 }
1002

 

posted @ 2014-05-31 21:26  海拉鲁的林克  阅读(323)  评论(0编辑  收藏  举报