给定一棵树,树中包含 n 个节点(编号 1∼n),其中第 ii 个节点的权值为 ai。
初始时,1 号节点为树的根节点。
现在要对该树进行 m 次操作,操作分为以下 4 种类型:
1 u v k
,修改路径上节点权值,将节点 u 和节点 v 之间路径上的所有节点(包括这两个节点)的权值增加 kk。2 u k
,修改子树上节点权值,将以节点 u 为根的子树上的所有节点的权值增加 k。3 u v
,询问路径,询问节点 u 和节点 v 之间路径上的所有节点(包括这两个节点)的权值和。4 u
,询问子树,询问以节点 u 为根的子树上的所有节点的权值和。
输入格式
第一行包含一个整数 n,表示节点个数。
第二行包含 n 个整数,其中第 i 个整数表示 ai。
接下来 n−1 行,每行包含两个整数 x,y,表示节点 x 和节点 y 之间存在一条边。
再一行包含一个整数 m,表示操作次数。
接下来 m 行,每行包含一个操作,格式如题目所述。
输出格式
对于每个操作 3 和操作 4,输出一行一个整数表示答案。
数据范围
1≤n,m≤105
0≤ai,k≤105
1≤u,v,x,y≤n
输入样例:
5
1 3 7 4 5
1 3
1 4
1 5
2 3
5
1 3 4 3
3 5 4
1 3 5 10
2 3 5
4 1
输出样例:
16
69
解析:
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <utility>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <math.h>
#include <map>
#include <sstream>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <stdio.h>
#include <tuple>
using namespace std;
/*
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
*/
typedef long long LL;
#define int long long
#define ld long double
//#define INT __int128
const LL INF = 0x3f3f3f3f3f3f3f3f;
typedef unsigned long long ULL;
typedef pair<long long, long long> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const int inf = 0x3f3f3f3f;
const LL mod = 998244353;
const ld eps = 1e-12;
const int N = 1e5 + 10, M = 2 * N + 10;
int n, Q;
int w[N], nw[N], id[N], fa[N], tot;
int dep[N], son[N], top[N], siz[N];
int h[N], e[M], ne[M], idx;
struct TREE {
int l, r;
int fg, sum;
}tr[N << 2];
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
e[idx] = a, ne[idx] = h[b], h[b] = idx++;
}
void dfs1(int u, int p, int d) {
siz[u] = 1, fa[u] = p, dep[u] = d;
int mx = 0;
for (int i = h[u]; i != -1; i = ne[i]) {
int j = e[i];
if (j == p)continue;
dfs1(j, u, d + 1);
siz[u] += siz[j];
if (siz[son[u]] < siz[j])son[u] = j;
}
}
void dfs2(int u, int link) {
id[u] = ++tot, nw[tot] = w[u], top[u] = link;
if (son[u])dfs2(son[u], link);
for (int i = h[u]; i != -1; i = ne[i]) {
int j = e[i];
if (j == fa[u] || j == son[u])continue;
dfs2(j, j);
}
}
#define ls u<<1
#define rs u<<1|1
void up(int u) {
tr[u].sum = tr[ls].sum + tr[rs].sum;
}
void down(int u) {
if (tr[u].fg) {
tr[ls].fg += tr[u].fg;
tr[ls].sum += tr[u].fg * (tr[ls].r - tr[ls].l + 1);
tr[rs].fg += tr[u].fg;
tr[rs].sum += tr[u].fg * (tr[rs].r - tr[rs].l + 1);
tr[u].fg = 0;
}
}
void build(int u, int l, int r) {
tr[u].l = l, tr[u].r = r;
if (l == r) {
tr[u].sum = nw[l];
return;
}
int mid = l + r >> 1;
build(ls, l, mid), build(rs, mid + 1, r);
up(u);
}
void modify(int u, int l, int r, int k) {
if (l <= tr[u].l && tr[u].r <= r) {
tr[u].sum += k * (tr[u].r - tr[u].l + 1);
tr[u].fg += k;
return;
}
down(u);
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid)modify(ls, l, r, k);
if (r > mid)modify(rs,l, r, k);
up(u);
}
int query(int u, int l, int r) {
if (l <= tr[u].l && tr[u].r <= r) {
return tr[u].sum;
}
down(u);
int mid = tr[u].l + tr[u].r >> 1;
int ret = 0;
if (l <= mid)ret += query(ls, l, r);
if (r > mid)ret += query(rs, l, r);
up(u);
return ret;
}
void path(int u, int v, int k) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]])swap(u, v);
modify(1, id[top[u]], id[u], k);
//cout << "------------" << u << " " << v << " " << top[u] << " " << top[v] << endl;
//cout << "++++++++++++++++++++ " << u << " " << top[u] << " " << id[u] << " " << id[top[u]] << endl;
u = fa[top[u]];
}
if (dep[u] < dep[v])swap(u, v);
//cout << "++++++++++++" << u << " " << v << " " << id[u] << " " << id[v] << endl;
modify(1, id[v], id[u], k);
}
int ask(int u, int v) {
int ret = 0;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]])swap(u, v);
ret += query(1, id[top[u]], id[u]);
//cout << "==================== " << u << " " << top[u] << " " << id[u] << " " << id[top[u]] << endl;
u = fa[top[u]];
}
if (dep[u] < dep[v])swap(u, v);
ret += query(1, id[v], id[u]);
//cout << "================" << u << " " << v << " " << id[u] << " " << id[v] << endl;
return ret;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> n;
memset(h, -1, sizeof h);
for (int i = 1; i <= n; i++) {
cin >> w[i];
}
for (int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
add(a, b);
}
dfs1(1,0,1);
dfs2(1, 1);
build(1, 1, n);
/*cout << "_____________________________" << endl;
for (int i = 1; i <= n; i++) {
cout << id[i] << " ";
}
cout << endl;
cout << endl;*/
cin >> Q;
int op;
while (Q--) {
cin >> op;
if (op == 1) {
int u, v, k;
cin >> u >> v >> k;
path(u, v, k);
}
else if (op == 2) {
int u, k;
cin >> u >> k;
modify(1, id[u], id[u] + siz[u]-1,k);
}
else if (op == 3) {
int u, v;
cin >> u >> v;
cout << ask(u, v) << endl;
}
else {
int u;
cin >> u;
//cout << "----------------" << id[u] << " " << id[u] + siz[u]-1 << endl;
cout << query(1, id[u], id[u] + siz[u]-1) << endl;
}
}
return 0;
}
/*
5
1 3 7 4 5
1 3
1 4
1 5
2 3
6
3 5 4
1 3 4 3
3 1 1
3 4 4
3 5 5
3 5 4
5
1 3 7 4 5
1 3
1 4
1 5
2 3
10
1 3 4 3
3 5 4
1 3 5 10
3 3 3
3 1 1
3 5 5
3 3 5
2 3 5
3 2 2
4 1
*/