列表

详情


NC204871. 求和

描述

已知有  个节点,有  条边,形成一个树的结构。

给定一个根节点 ,每个节点都有一个权值,节点i的权值为

给  个操作,操作有两种类型:

1 a x :表示将节点  的权值加上 

2 a :表示求  节点的子树上所有节点的和(包括  节点本身)

输入描述

第一行给出三个正整数 ,表示树的节点数、操作次数、和这棵树的根节点.

第二行给出  个正整数,第  个正整数表示第  个节点的权值 

下面  行每行两个正整数 ,表示边的两个端点

接下来  行,每行给出一个操作

输出描述

对于每个类型为 2 的操作,输出一行一个正整数,表示以  为根的子树的所有节点的权值和

示例1

输入:

5 6 1
1 2 3 4 5
1 3
1 2
2 4
2 5
1 2 10
1 3 10
1 4 5
1 5 1
2 3
2 2

输出:

13
27

原站题解

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

C++11(clang++ 3.9) 解法, 执行用时: 1638ms, 内存消耗: 116552K, 提交时间: 2020-04-18 19:32:42

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

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

C++14(g++5.4) 解法, 执行用时: 1500ms, 内存消耗: 112516K, 提交时间: 2020-04-19 11:28:40

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int tr[N],n,m,k,a[N],in[N],out[N],tot;
typedef long long ll;
#define lowbit(x) (x&-x)
vector<int>e[N];
void upd(int i,int x){
	while(i<=n){
		tr[i]+=x;
		i+=lowbit(i);
	}
}
ll sum(int i){
	ll sum=0;
	while(i) sum+=tr[i],i-=lowbit(i);
	return sum;
}
void dfs(int u,int fa){
	in[u]=++tot,upd(tot,a[u]);
	for(auto v:e[u]){
		if(v!=fa) dfs(v,u);
	}
	out[u]=tot;
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1,u,v;i<n;i++){
		scanf("%d%d",&u,&v);
		e[u].push_back(v),e[v].push_back(u);
	}
	dfs(k,0);
	while(m--){
		int op,a,x;
		scanf("%d%d",&op,&a);
		if(op==1) scanf("%d",&x),upd(in[a],x);
		else printf("%lld\n",sum(out[a])-sum(in[a]-1));
	}
	return 0;
} 

上一题