您的位置:首页 > 产品设计 > UI/UE

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

2014-05-31 21:26 369 查看
先上题目:

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


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

[align=left]Input[/align]
  第一行为数据组数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行为描述中的三种操作。

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

[align=left]Sample Input[/align]

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

[align=left]Sample Output[/align]

Case #1:

15
22

18
Case #2:

36
33

6

3

[align=left]Source[/align]
2014年百度之星程序设计大赛 - 复赛

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

上代码:

#include <cstdio>
#include <cstring>
#include <utility>
#define MAX 10002
using namespace std;
typedef pair<int,int> pii;

int n,tot;
int p[MAX];
int fa[MAX];
int w[MAX];
int s[MAX];
pii e[MAX<<1];
char q[10];
bool f;

void reset(){
memset(p,-1,sizeof(int)*(n+1));
tot=0;
}

void add(int u,int v){
e[tot].first=v; e[tot].second=p[u]; p[u]=tot++;
e[tot].first=u; e[tot].second=p[v]; p[v]=tot++;
}

int deal(int u,int t){
int c=0;
s[u]=0;
fa[u]=t;
for(int v=p[u];v!=-1;v=e[v].second){
if(e[v].first!=t){
c = deal(e[v].first,u);
s[u]+=c;
}
}
s[u]+=w[u];
return s[u];
}

void C(int a,int v){
int c = w[a];
while(a!=0){
s[a] = s[a] - c + v;
a = fa[a];
}
}

void R(int r,int t){
s[r]=0;
for(int i=p[r];i!=-1;i=e[i].second){
if(e[i].first==t) continue;
if(e[i].first==fa[r]) R(fa[r],r);
s[r]+=s[e[i].first];
fa[e[i].first]=r;
}
s[r]+=w[r];
}

int main()
{
int t,u,v,a,m;
//freopen("data.txt","r",stdin);
scanf("%d",&t);
for(int z=1;z<=t;z++){
printf("Case #%d:\n",z);
scanf("%d",&n);
reset();
for(int i=1;i<n;i++){
scanf("%d %d",&u,&v);
add(u,v);
}
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
deal(1,0);
scanf("%d",&a);
while(a--){
scanf("%s %d",q,&m);
if(q[0]=='Q'){
printf("%d\n",s[m]);
}else if(q[0]=='C'){
scanf("%d",&v);
C(m,v);
w[m]=v;
}else{
R(m,0);
fa[m]=0;
}
}
}
return 0;
}


1002
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: