Description
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
Input
第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1
行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。再接下来 M 行,每行分别表示一次操作。其中
第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
Output
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
题解:刷水有益健康...
#include <bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin), freopen(s".out","w",stdout)
#define maxn 110000
#define ll long long
#define lson (x<<1)
#define rson ((x<<1)|1)
using namespace std;
int hd[maxn], to[maxn << 1], nex[maxn << 1], st[maxn], ed[maxn];
int fa[maxn], dep[maxn], dfn[maxn], ln[maxn], hson[maxn], siz[maxn], bot[maxn], top[maxn];
int edges, n , Q, tim;
ll val[maxn];
void add(int u, int v)
{
nex[++edges] = hd[u], hd[u] = edges, to[edges] = v;
}
void dfs1(int u, int ff)
{
fa[u] = ff, dep[u] = dep[ff] + 1, siz[u] = 1;
for(int i = hd[u]; i ; i = nex[i])
{
int v = to[i];
if(v == ff) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > siz[hson[u]]) hson[u] = v;
}
}
void dfs2(int u, int tp)
{
top[u] = tp, ln[++tim] = u, dfn[u] = tim, st[u] = tim;
if(hson[u])
dfs2(hson[u], tp), bot[u] = bot[hson[u]];
else
bot[u] = u;
for(int i = hd[u]; i ; i = nex[i])
{
int v = to[i];
if(v == fa[u] || v == hson[u]) continue;
dfs2(v, v);
}
ed[u] = tim;
}
struct Node
{
ll lazy, val, sumv;
}t[maxn << 3];
void mark(int l, int r, int x, ll d)
{
t[x].lazy += d;
ll tmp = r - l + 1;
t[x].sumv += 1ll*tmp*1ll*d;
}
void pushdown(int l, int r, int x)
{
if(!t[x].lazy) return;
int mid = (l + r) >> 1;
if(mid >= l) mark(l, mid, lson, t[x].lazy);
if(r > mid) mark(mid + 1, r, rson, t[x].lazy);
t[x].lazy = 0;
}
void build(int l, int r, int x)
{
if(l == r)
{
t[x].sumv = t[x].val = val[ln[l]];
return;
}
int mid = (l + r) >> 1;
build(l, mid, lson);
build(mid + 1, r, rson);
t[x].sumv = t[lson].sumv + t[rson].sumv;
}
void update(int l, int r, int x, int L, int R, ll d)
{
pushdown(l, r, x);
if(l >= L && r <= R)
{
mark(l, r, x, d);
return;
}
int mid = (l + r) >> 1;
if(L <= mid) update(l, mid, lson, L, R, d);
if(R > mid) update(mid + 1, r, rson, L, R, d);
t[x].sumv = t[lson].sumv + t[rson].sumv;
}
ll query(int l, int r, int x, int L, int R)
{
pushdown(l, r, x);
if(l >= L && r <= R) return t[x].sumv;
int mid = (l + r) >> 1;
ll tmp = 0;
if(L <= mid) tmp += query(l, mid, lson, L, R);
if(R > mid) tmp += query(mid + 1, r, rson, L, R);
return tmp;
}
void modify1(int x, ll d)
{
update(1, n, 1, dfn[x], dfn[x], d);
}
void modify2(int x, ll d)
{
update(1, n, 1, st[x], ed[x], d);
}
ll Query(int x)
{
ll tmp = 0;
while(x)
{
tmp += query(1, n, 1, dfn[top[x]], dfn[x]);
x = fa[top[x]];
}
return tmp;
}
int main()
{
// setIO("input");
scanf("%d%d",&n,&Q);
for(int i = 1;i <= n; ++i) scanf("%lld",&val[i]);
for(int i = 1, u , v; i < n; ++i)
{
scanf("%d%d",&u,&v), add(u, v), add(v, u);
}
dfs1(1, 0), dfs2(1, 1), build(1, n, 1);
while(Q--)
{
int opt, x;
ll a;
scanf("%d",&opt);
if(opt == 1)
{
scanf("%d%lld",&x,&a), modify1(x, a);
}
if(opt == 2)
{
scanf("%d%lld",&x,&a), modify2(x, a);
}
if(opt == 3)
{
scanf("%d",&x);
printf("%lld\n",Query(x));
}
}
return 0;
}