列表

详情


NC23051. 华华和月月种树

描述

华华看书了解到,一起玩养成类的游戏有助于两人培养感情。所以他决定和月月一起种一棵树。因为华华现在也是信息学高手了,所以他们种的树是信息学意义下的。
华华和月月一起维护了一棵动态有根树,每个点有一个权值。刚开存档的时候,树上只有 0 号节点,权值为 0 。接下来有两种操作:
操作 1:输入格式,表示月月氪金使节点 i 长出了一个新的儿子节点,权值为0,编号为当前最大编号 +1(也可以理解为,当前是第几个操作 1,新节点的编号就是多少)。
操作 2:输入格式 ,表示华华上线做任务使节点 i 的子树中所有节点(即它和它的所有子孙节点)权值加 a 。
但是月月有时会检查华华有没有认真维护这棵树,会作出询问:
询问 3:输入格式,华华需要给出 i 节点此时的权值。
华华当然有认真种树了,不过还是希望能写个程序以备不时之需。

输入描述

第一行一个正整数M,接下来M行,每行先输入一个正整数O表示操作类型,再输入一个非负整数i表示操作或询问的节点编号,如果O=2,再输入一个正整数a。

输出描述

对于每个询问3,输出一个非负整数表示询问的答案。

示例1

输入:

9
1 0
2 0 1
3 0
3 1
1 0
1 1
2 0 2
3 1
3 3

输出:

1
1
3
2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 118ms, 内存消耗: 23968K, 提交时间: 2020-08-20 12:05:47

#include<bits/stdc++.h>
using namespace std;

vector<int>R[400005];
int n=0,tot=0,S[400005]={0},in[400005],out[400005],op[400005],x[400005],y[400005]; 
int lowbit(int x)
{
	return x&(-x);
}
void update(int i,int x)
{
	while(i<=n+1)S[i]+=x,i+=lowbit(i);
}
int getsum(int i)
{
	int s=0;
	while(i)s+=S[i],i-=lowbit(i);
	return s;
}
void DFS(int x)
{
	in[x]=++tot;
	for(int i=0;i<R[x].size();i++)DFS(R[x][i]);
	out[x]=tot;
}
int main()
{
	int i,j,m;
	scanf("%d",&m);
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&op[i],&x[i]);
		if(op[i]==2)scanf("%d",&y[i]);
		if(op[i]==1)R[x[i]].push_back(++n),y[i]=n;
	}
	DFS(0);
	for(i=1;i<=m;i++)
	{
		if(op[i]==1)j=getsum(in[y[i]]),update(in[y[i]],-j),update(in[y[i]]+1,j);
		else if(op[i]==2)update(in[x[i]],y[i]),update(out[x[i]]+1,-y[i]);
		else printf("%d\n",getsum(in[x[i]]));
	}
}

C++11(clang++ 3.9) 解法, 执行用时: 114ms, 内存消耗: 22424K, 提交时间: 2020-08-20 18:28:46

#include<bits/stdc++.h>
using namespace std;
vector<int>R[400005];
int n=0,tot=0,S[400005]={0},in[400005],out[400005],op[400005],x[400005],y[400005]; 
int lowbit(int x){
	return x&(-x);
}
void update(int i,int x){
	while(i<=n+1)S[i]+=x,i+=lowbit(i);
}
int getsum(int i){
	int s=0;
	while(i)s+=S[i],i-=lowbit(i);
	return s;
}
void DFS(int x){
	in[x]=++tot;
	for(int i=0;i<R[x].size();i++)DFS(R[x][i]);
	out[x]=tot;
}
int main(){
	int i,j,m;
	scanf("%d",&m);
	for(i=1;i<=m;i++){
		scanf("%d%d",&op[i],&x[i]);
		if(op[i]==2)scanf("%d",&y[i]);
		if(op[i]==1)R[x[i]].push_back(++n),y[i]=n;
	}
	DFS(0);
	for(i=1;i<=m;i++){
		if(op[i]==1)j=getsum(in[y[i]]),update(in[y[i]],-j),update(in[y[i]]+1,j);
		else if(op[i]==2)update(in[x[i]],y[i]),update(out[x[i]]+1,-y[i]);
		else printf("%d\n",getsum(in[x[i]]));
	}
}

上一题