1.点上记录值为相对于子节点的差分,子树差分和为根的和
2.求LCA有多种算法,选择其中一种倍增算法
#include<bits/stdc++.h>
#define pb push_back
const int N = 1e6 + 5;
using namespace std;
typedef long long ll;
#define debug(x) cout<<#x<<" is "<<x<<endl
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
int n,m,R;
vector<int> g[N];
int vv[N];
int tot = 0;
int l[N],r[N],fa[N][20];
inline int read()
{
int X=0; bool flag=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
if(flag) return X;
return ~(X-1);
}
inline void write(ll X)
{
if(X<0) {X=~(X-1); putchar('-');}
if(X>9) write(X/10);
putchar(X%10+'0');
}
int deep[N];
void dfs(int u,int pre,int dep){
deep[u] = dep;
l[u] = ++tot;
for(int i = 0;i < g[u].size();i++){
int v = g[u][i];
if(v == pre)continue;
dfs(v,u,dep + 1);
fa[v][0] = u;
}
r[u] = tot;
}
void init(){
for(int j=0;(1<<(j+1))<n;j++)
for(int i=1;i<=n;i++)
{
if(fa[i][j]<=0) fa[i][j+1]=0;
else fa[i][j+1]=fa[fa[i][j]][j];
}
}
int lca(int u,int v)
{
if(deep[u]>deep[v]) swap(u,v);
int temp=deep[v]-deep[u];
for(int i=0;(1<<i)<=temp;i++)
{
if((1<<i)&temp) v=fa[v][i];
}
if(v==u) return u;
for(int i=(int)(log(n*1.0)/log(2.0));i>=0;i--)
{
if(fa[u][i]!=fa[v][i])
{
u=fa[u][i];
v=fa[v][i];
}
}
return fa[u][0];
}
struct BIT{
ll a[N];
int n;
void init(int nn){
n = nn;
for(int i = 1;i <= n;i++)a[i] = 0;
}
int lowbit(int x){return x&(-x);}
void update(int i,ll x){
if(i == 0)return;
while(i <= n){
a[i] += x;
i += lowbit(i);
}
}
ll query(int i){
ll ans = 0;
while(i > 0){
ans += a[i];
i -= lowbit(i);
}
return ans;
}
}t1,t2;
void update(int u,int v,ll val){
if(u != v){
int ca = lca(u,v);
t1.update(l[u],val);
t1.update(l[v],val);
t1.update(l[ca],-val);
t1.update(l[fa[ca][0]],-val);
t2.update(l[u],val * deep[u]);
t2.update(l[v],val * deep[v]);
t2.update(l[ca],- val * deep[ca]);
t2.update(l[fa[ca][0]],-val * deep[fa[ca][0]]);
}else{
t1.update(l[u],val);
t1.update(l[fa[u][0]],-val);
t2.update(l[u],val * deep[u]);
t2.update(l[fa[u][0]],-val * deep[fa[u][0]]);
}
}
void solve(){
n = read();m = read(),R = read();
t1.init(n);t2.init(n);
for(int i = 1;i <= n;i++)
vv[i] = read();
for(int i = 1;i <= n - 1;i++){
int u,v;
u = read(),v = read();
g[u].pb(v);
g[v].pb(u);
}
dfs(R,-1,1);
init();
for(int i = 1;i <= n;i++){
update(i,i,vv[i]);
}
while(m--){
int op,x,y,z;
op = read();
if(op == 1){
x = read(),y = read(),z = read();
update(x,y,z);
}else {
x = read();
ll ans;
if(op == 2)ans = t1.query(r[x]) - t1.query(l[x] - 1);
else {
ll tt1 = t1.query(r[x]) - t1.query(l[x] - 1);
ll tt2 = t2.query(r[x]) - t2.query(l[x] - 1);
ans = tt2 - tt1 * (deep[x] - 1);
}
write(ans);
puts("");
}
}
}
inline void fastIO(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
}
int main(){
//fastIO();
solve();
return 0;
}