Description
这是一道模板题。
给定一棵 n个节点的树,初始时该树的根为 1 号节点,每个节点有一个给定的权值。下面依次进行 m 个操作,操作分为如下五种类型:
- 换根:将一个指定的节点设置为树的新根。
- 修改路径权值:给定两个节点,将这两个节点间路径上的所有节点权值(含这两个节点)增加一个给定的值。
- 修改子树权值:给定一个节点,将以该节点为根的子树内的所有节点权值增加一个给定的值。
- 询问路径:询问某条路径上节点的权值和。
- 询问子树:询问某个子树内节点的权值和
Input
第一行为一个整数 n,表示节点的个数。
第二行 n 个整数表示第 i个节点的初始权值 ai。
第三行 n−1 个整数,表示 i+1 号节点的父节点编号fi+1(1⩽fi+1⩽n)。
第四行一个整数 m,表示操作个数。
接下来 m 行,每行第一个整数表示操作类型编号:(1⩽u,v⩽n)
- 若类型为 1,则接下来一个整数 u,表示新根的编号。
- 若类型为 2,则接下来三个整数 u,v,k,分别表示路径两端的节点编号以及增加的权值。
- 若类型为 3,则接下来两个整数 u,k,分别表示子树根节点编号以及增加的权值。
- 若类型为 4,则接下来两个整数 u,v,表示路径两端的节点编号。
- 若类型为 5,则接下来一个整数 u,表示子树根节点编号。
Output
对于每一个类型为 4或 5 的操作,输出一行一个整数表示答案。
-
Sample Input
-
6 1 2 3 4 5 6 1 2 1 4 4 6 4 5 6 2 2 4 1 5 1 1 4 3 1 2 4 2 5
-
Sample Output
-
15 24 19
#include<bits/stdc++.h>
#define ls ( u << 1 )
#define rs ( ( u <<1 ) | 1 )
#define mid ( ( l + r ) >> 1 )
#define int long long
#define N 100005
using namespace std;
signed n, a[N], m, x;
signed idx[N], u, v, w;
int tree[N<<2], add[N<<2];
signed adj[N], nextone[N<<1];
signed to[N<<1], cnt, rightson;
signed son[N], size[N];
signed deep[N], fath[N];
signed pos[N], out[N];
signed top[N], tot;
inline void addedge( int u, int v )
{
nextone[++cnt] = adj[u];
adj[u] = cnt;
to[cnt] = v;
}
inline void pushup( int u )
{
tree[u] = tree[ls] + tree[rs];
}
inline void pushdown( int u, int l, int r )
{
if( !add[u] ) return;
add[ls] += add[u];
add[rs] += add[u];
tree[ls] += 1ll * ( mid - l + 1 ) * add[u];
tree[rs] += 1ll * ( r - mid ) * add[u];
add[u] = 0;
}
void build( int u, int l, int r )
{
if( l == r )
{
tree[u] = a[idx[l]];
return;
}
build( ls, l, mid );
build( rs, mid + 1, r );
pushup(u);
}
void update( int u, int l, int r, int st, int des, int k )
{
if( st <= l && r <= des )
{
add[u] += k;
tree[u] += 1ll * ( r - l + 1 ) * k;
return;
}
pushdown( u, l, r );
if( st <= mid )
{
update( ls, l, mid, st, des, k );
}
if( mid < des )
{
update( rs, mid + 1, r, st, des, k );
}
pushup(u);
}
int query( int u, int l, int r, int st, int des )
{
if( st <= l && r <= des )
{
return tree[u];
}
pushdown( u, l, r );
int res = 0;
if( st <= mid )
{
res += query( ls, l, mid, st, des );
}
if( mid < des )
{
res += query( rs, mid + 1, r, st, des );
}
pushup(u);
return res;
}
void dfs1( int u )
{
size[u] = 1;
for( int i = adj[u]; i; i = nextone[i] )
{
int v = to[i];
if( v == fath[u] )
{
continue;
}
fath[v] = u;
deep[v] = deep[u] + 1;
dfs1(v);
size[u] += size[v];
if( size[v] > size[son[u]] )
{
son[u] = v;
}
}
}
void dfs2( int u, int tp )
{
pos[u] = ++tot;
idx[tot] = u;
top[u] = tp;
if( !son[u] )
{
return void( out[u] = tot );
}
dfs2( son[u], tp );
for( int i = adj[u]; i; i = nextone[i] )
{
if( to[i] == fath[u] || to[i] == son[u] )
{
continue;
}
dfs2( to[i], to[i] );
}
out[u] = tot;
}
int lca( int u, int v )
{
while( top[u] != top[v] )
{
if( deep[top[u]] < deep[top[v]] )
{
swap(u,v);
}
u = fath[top[u]];
}
return deep[u] > deep[v] ? v : u;
}
int find( int u, int v )
{
while( top[u] != top[v] )
{
if( deep[top[u]] < deep[top[v]] )
{
swap(u,v);
}
if( fath[top[u]] == v )
{
return top[u];
}
u = fath[top[u]];
}
if( deep[u] < deep[v] )
{
swap( u, v );
}
return son[v];
}
void update2( int u, int v, int k )
{
while( top[u] != top[v] )
{
if( deep[top[u]] < deep[top[v]] )
{
swap( u, v );
}
update( 1, 1, n, pos[top[u]], pos[u], k );
u = fath[top[u]];
}
if( deep[u] < deep[v] )
{
swap( u, v );
}
update( 1, 1, n, pos[v], pos[u], k );
}
void update3( int u, int k )
{
if( u == rightson )
{
return update( 1, 1, n, 1, n, k );
}
int l = lca( u, rightson);
if( l != u )
{
return update( 1, 1, n, pos[u], out[u], k );
}
int son2 = find(u,rightson);
update( 1, 1, n, 1, n, k );
update( 1, 1, n, pos[son2], out[son2], -k );
}
int query2( int u, int v )
{
int res = 0;
while( top[u] != top[v] )
{
if( deep[top[u]] < deep[top[v]] )
{
swap( u, v );
}
res += query( 1, 1, n, pos[top[u]], pos[u] );
u = fath[top[u]];
}
if( deep[u] < deep[v] )
{
swap( u, v );
}
res += query( 1, 1, n, pos[v], pos[u] );
return res;
}
int query3( int u )
{
if( u == rightson )
{
return query( 1, 1, n, 1, n );
}
int l = lca( u, rightson );
if( l != u )
{
return query( 1, 1, n, pos[u], out[u] );
}
int son2 = find( u, rightson );
int res = 0;
res += query( 1, 1, n, 1, n );
res -= query( 1, 1, n, pos[son2], out[son2] );
return res;
}
signed main()
{
cin >> n;
for( int i = 1; i <= n; i++ )
{
cin >> a[i];
}
for( int i = 1; i <= n - 1; i++ )
{
cin >> u;
addedge( i + 1, u );
addedge( u, i + 1 );
}
cin >> m;
dfs1( rightson = 1 );
dfs2( 1, 1 );
build( 1, 1, n );
for( int i = 1; i <= m; i++ )
{
cin >> x;
if( x == 1 )
{
cin >> rightson;
}
else if( x == 2 )
{
cin >> u >> v >> w;
update2( u, v, w );
}
else if( x == 3 )
{
cin >> u >> v;
update3( u, v );
}
else if( x == 4 )
{
cin >> u >> v;
cout << query2( u, v ) << "\n";
}
else
{
cin >> u;
cout << query3(u) << '\n';
}
}
}