19 pts:
// 13:05
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define lc p<<1
#define rc p<<1|1
inline int in(){
char a=getchar();int k=0,kk=1;
while(!isdigit(a)){if(a=='-')kk=-1;a=getchar();}
while(isdigit(a)){k=k*10+a-'0',a=getchar();}
return k*kk;
}
const int N = 1e5 + 5;
struct node{int nxt,v;}e[2*N];
int head[N],tot,mod;
void add(int u,int v){e[++tot].v=v,e[tot].nxt=head[u],head[u] = tot;}
int son[N],siz[N],f[N],dep[N];
void dfs1(int x,int fa,int deep){
f[x]=fa,siz[x]=1,dep[x]=deep;
int maxson = -1;
for(int i=head[x];i;i=e[i].nxt){
int v = e[i].v;
if(v!=fa){
dfs1(v,x,deep+1);
siz[x] += siz[v];
if(siz[v]>maxson) maxson = siz[v],son[x] = v;
}
}
}
int id[N],wt[N],cnt,top[N],w[N];
void dfs2(int x,int topf){
id[x] = ++cnt, wt[cnt] = w[x], top[x] = topf;
if(!son[x]) return;
dfs2(son[x],topf);
for(int i=head[x];i;i=e[i].nxt){
int v=e[i].v;
if(v!=f[x]&&v!=son[x]){
dfs2(v,v);
}
}
}
struct node1{int l,r,lazy,x;}tr[N*4];
void push_up(int p){tr[p].x=(tr[lc].x+tr[rc].x)%mod;}
void push_down(int p) {
if(tr[p].lazy){
int k = tr[p].lazy;
tr[lc].x = (tr[lc].x + (tr[lc].r-tr[lc].l+1)*k%mod) % mod;
tr[lc].lazy = (tr[lc].lazy + k) % mod;
tr[rc].x = (tr[rc].x + (tr[rc].r-tr[rc].l+1)*k%mod) % mod;
tr[rc].lazy = (tr[rc].lazy + k) % mod;
tr[p].lazy = 0;
}
}
void build(int p,int l,int r){
tr[p].l = l, tr[p].r = r;
if(l==r){
tr[p].x = wt[l]%mod;
return;
}
int m = (l+r)>>1;
build(lc,1,m),build(rc,m+1,r);
push_up(p);
}
int query(int p,int l,int r){
if(l<=tr[p].l&&r>=tr[p].r){
return tr[p].x%mod;
}
push_down(p);
int ans = 0,m = (tr[p].l+tr[p].r)/2;
if(l<=m) ans = (ans +query(lc,l,r)) % mod;
if(r>m) ans = (ans + query(rc,l,r)) % mod;
return ans;
}
void change(int p,int l,int r,int k){
// cout << p << " " << l << " " << r << " " << k << endl;
k %= mod;
if(l<=tr[p].l&&r>=tr[p].r){
tr[p].x = (tr[p].x + (tr[p].r-tr[p].l+1)*k%mod) % mod;
tr[p].lazy = (tr[p].lazy + k) % mod;
return;
}
push_down(p);
int m = (tr[p].l+tr[p].r)/2;
if(l<=m) change(lc,l,r,k);
if(r>m) change(rc,l,r,k);
push_up(p);
}
int tr_query(int x,int y){
int ans = 0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans = (ans + query(1,id[top[x]],id[x]) % mod) % mod;
x = f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans = (ans + query(1,id[x],id[y])) % mod;
return ans;
}
void tr_change(int x,int y,int k){
k %= mod;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
change(1,id[top[x]],id[x],k);
x = f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
change(1,id[x],id[y],k);
}
void tmpadd(int x,int k){
k %= mod;
change(1,id[x],id[x]+siz[x]-1,k);
}
int tmpquery(int x){
return query(1,id[x],id[x]+siz[x]-1) % mod;
}
int n,m,r;
signed main(){
// freopen("P3384_1.in","r",stdin);
// freopen("mine.txt","w",stdout);
n = in(), m = in(), r = in(), mod = in();
for(int i=1;i<=n;i++) w[i] = in();
for(int i=1;i<n;i++){
int u = in(), v = in();
add(u,v), add(v,u);
}
dfs1(r,0,1);
dfs2(r,r);
build(1,1,n);
// for(int i=1;i<=n;i++) cout << top[i] << " ";
// puts("");
while(m--){
int op = in(), x = in(),y,z;
if(op==1){
y=in(),z=in();
tr_change(x,y,z);
}else if(op==2){
y = in();
printf("%lld\n",tr_query(x,y)%mod);
}else if(op==3){
y = in();
tmpadd(x,y);
}else{
printf("%lld\n",tmpquery(x)%mod);
}
}
return 0;
}
AC
// 20:26:30
#include<bits/stdc++.h>
using namespace std;
#define lc p<<1
#define rc p<<1|1
#define int long long
const int N = 1e5 + 5;
struct node{
int v,nxt;
}e[N*2];
struct node1{
int x,l,r,lazy;
}tr[N<<2];
int n,m,r,head[N],mod,tot,w[N],wt[N];
void add(int u,int v){
e[++tot].v = v;
e[tot].nxt = head[u];
head[u] = tot;
}
void push_up(int p){
tr[p].x = (tr[lc].x + tr[rc].x) % mod;
}
void push_down(int p){
if(tr[p].lazy){
int k = tr[p].lazy;
tr[lc].x = (tr[lc].x+(tr[lc].r-tr[lc].l+1)*k) % mod;
tr[rc].x = (tr[rc].x+(tr[rc].r-tr[rc].l+1)*k) % mod;
tr[lc].lazy = (tr[lc].lazy+k) % mod;
tr[rc].lazy = (tr[rc].lazy+k) % mod;
tr[p].lazy = 0;
}
}
void build(int p,int l,int r){
tr[p].l = l, tr[p].r = r;
if(l==r){
tr[p].x = wt[l] % mod;
return;
}
int m = l + r >> 1;
build(lc,l,m),build(rc,m+1,r),push_up(p);
}
int query(int p,int l,int r){
if(l<=tr[p].l&&r>=tr[p].r){
return tr[p].x % mod;
}
push_down(p);
int ans = 0, m = tr[p].l + tr[p].r >> 1;
if(l<=m) ans += query(lc,l,r) % mod;
if(r>m) ans = (ans + query(rc,l,r)) % mod;
return ans;
}
void change(int p,int l,int r,int k){
if(l<=tr[p].l&&r>=tr[p].r){
tr[p].x = (tr[p].x+(tr[p].r-tr[p].l+1)*k) % mod;
tr[p].lazy = (tr[p].lazy+k) % mod;
return;
}
push_down(p);
int m = tr[p].l + tr[p].r >> 1;
if(l<=m) change(lc,l,r,k);
if(r>m) change(rc,l,r,k);
push_up(p);
}
inline int in(){
char a=getchar();
int k=0,kk=1;
while(a>'9'||a<'0'){
if(a=='-') kk = -1;
a = getchar();
}
while(a>='0'&&a<='9'){
k=k*10+a-'0',a=getchar();
}
return k*kk;
}
int dep[N],fa[N],son[N],siz[N],id[N],top[N],cnt;
void dfs1(int x,int f,int deep){
fa[x] = f, dep[x] = deep, siz[x] = 1;
int maxson = -1;
for(int i=head[x];i;i=e[i].nxt){
int v = e[i].v;
if(v==f) continue;
dfs1(v,x,deep+1);
siz[x] += siz[v];
if(siz[v]>maxson) son[x] = v, maxson = siz[v];
}
}
void dfs2(int x,int topf){
top[x] = topf, id[x] = ++cnt, wt[cnt] = w[x];
if(!son[x]) return;
dfs2(son[x],topf);
for(int i=head[x];i;i=e[i].nxt){
int v = e[i].v;
if(v==fa[x]||v==son[x]) continue;
dfs2(v,v);
}
}
void tr_change(int x,int y,int k){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
change(1,id[top[x]],id[x],k);
x = fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
change(1,id[x],id[y],k);
}
int tr_query(int x,int y){
int ans = 0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans = (ans + query(1,id[top[x]],id[x])) % mod;
x = fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans = (ans + query(1,id[x],id[y])) % mod;
return ans;
}
void tr_upson(int x,int k){
change(1,id[x],id[x]+siz[x]-1,k);
}
int tr_qson(int x){
return query(1,id[x],id[x]+siz[x]-1) % mod;
}
signed main(){
n = in(), m = in(), r = in(), mod = in();
for(int i=1;i<=n;i++) w[i] = in();
for(int i=1;i<n;i++){
int u=in(),v=in();
add(u,v),add(v,u);
}
dfs1(r,0,1);
dfs2(r,r);
build(1,1,n);
while(m--){
int op = in(), x = in(), y,z;
if(op==1){
y = in(), z = in();
tr_change(x,y,z);
}else if(op==2){
y = in();
printf("%lld\n",tr_query(x,y));
}else if(op==3){
y = in();
tr_upson(x,y);
}else{
printf("%lld\n",tr_qson(x));
}
}
return 0;
}
PS:和好基友比赛默写薯片结果调到现在,破防。