牛客小白月赛24—I.求和
牛客小白月赛24—I.求和
题目描述
已知有\(n\)个节点,有\(n-1\)条边,形成一个树的结构。
给定一个根节点\(k\),每个节点都有一个权值,节点\(i\)的权值为\(v_i\)。
给\(m\)个操作,操作有两种类型:
1 a x : 表示将节点\(a\)的权值加上x
2 a : 表示求\(a\)节点的子树上所有节点的和(包括\(a\)节点本身)
输入描述
第一行给出三个正整数 \(n,m,k\),表示树的节点数、操作次数、和这颗树的根节点,
第二行给出\(n\)个正整数,第\(i\)个正整数表示第\(i\)个节点的权值\(val_i\)
下面\(n-1\)行每行两个正整数\(u,v\),表示边的两个端点
接下来\(m\)行,每行给出一个操作
输出描述
对于每个类型为 2 的操作,输出一行一个正整数,表示以 \(a\) 为根的子树的所有节点的权值和
样例输入
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
备注
\(1\leq n,m\leq 1e6,1\leq k \leq n\)
\(1\leq u,v \leq n\)
\(1\leq a \leq n\)
\(-1e6\leq val_i,x \leq 1e6\)
建议使用scanf
读入
思路
DFS序加树状数组或者线段树维护前缀和
关于DFS序见:https://www.cnblogs.com/LeafLove/p/12730685.html
Code
#include <bits/stdc++.h>
#define CSE(x,y) memset(x,y,sizeof(x))
#define INF 0x3f3f3f3f
#define FAST ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll , ll> pll;
const int maxn = 2000111;
//graph_describe
int v[maxn],u[maxn],first[maxn],nxt[maxn],n,m,k,cnt;
ll val[maxn];
//dfs_order
int in[maxn],out[maxn],order;
//Tree_array
ll sum[maxn];
void add(int a,int b) {
cnt++;
u[cnt] = a; v[cnt] = b; nxt[cnt] = first[u[cnt]]; first[u[cnt]] = cnt;
return;
}
void dfs(int be,int fa) {
in[be] = ++order;
for(int i=first[be];i!=-1;i=nxt[i]) {
if(v[i] != fa) {
dfs(v[i],be);
}
}
out[be] = order;
return;
}
int lowbit(int x) { return x & (-x);}
ll get_ans(int x) {
ll ans = 0; while(x) {ans += sum[x];x -= lowbit(x);}
return ans;
}
void update(int x,ll w) {
while(x<=n) { sum[x] += w; x += lowbit(x);}
return;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
#endif
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++) {
scanf("%lld", &val[i]);
}
for(int i=1;i<=n;i++) first[i] = -1;
for(int i=1;i<n;i++) {
int a,b;
scanf("%d%d",&a,&b);
add(a,b); add(b,a);
}
dfs(k,-1);
for(int i=1; i<=n; i++) {
update(in[i],val[i]);
}
while(m--){
int d,a;
scanf("%d%d",&d,&a);
if(d==1) {
ll x;
scanf("%lld",&x);
update(in[a],x);
}
else
{
printf("%lld\n",get_ans(out[a]) - get_ans(in[a] - 1));
}
}
return 0;
}
第一次接触这种题时,真的是被这个做法深深吸引了