CC__DIAMOND @ 2024-07-16 18:21:50
#include <bits/stdc++.h>
#define BAR cout<<"*******\n";
#define fst first
#define snd second
#define INFILE(x) freopen(x,"r",stdin)
#define OUTFILE(x) freopen(x,"w",stdout)
#define eb_ emplace_back
#define ep_ emplace
#define mp_ make_pair
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3f
#define ADD(x,y) ((x+y)%mod)
#define SUB(x,y) ((x-y+mod)%mod)
using namespace std;
using ll=long long;
using ul=unsigned long long;
using ui=unsigned int;
using db=double;
using pii=pair<int,int>;
using pil=pair<int,ll>;
using pll=pair<ll,ll>;
constexpr int int_inf=0x3f3f3f3f;
constexpr ll ll_inf=0x3f3f3f3f3f3f3f3fll;
namespace Solution {
constexpr int N=1e5+10;
ll mod;
struct BIT {
int n;
ll val[N];
void init() {
n=0;
memset(val,0,sizeof(val));
}
void add(int x,ll v) {
for(;x<=n;x+=x&(-x)) val[x]=ADD(val[x],v);
}
ll query(int x) {
ll res=0;
for(;x;x-=x&(-x)) res=ADD(res,val[x]);
return res;
}
};
struct {
BIT d1,d2;
void init(ll src[],int n) {
d1.init();
d2.init();
d1.n=d2.n=n;
for(int i=1;i<=n;++i) {
d1.add(i,src[i]);
d2.add(i,i*src[i]%mod);
}
}
void add(int x,ll v) {
d1.add(x,v);
d2.add(x,x*v%mod);
d1.add(x+1,mod-v);
d2.add(x+1,mod-(x+1)*v%mod);
}
void add(int l,int r,ll v) {
d1.add(l,v);
d1.add(r+1,mod-v);
d2.add(l,l*v%mod);
d2.add(r+1,mod-(r+1)*v%mod);
}
ll query(int x) {
ll res=0;
res=ADD(res,(x+1)*d1.query(x));
res=SUB(res,d2.query(x));
return res;
}
ll query(int l,int r) {
return SUB(query(r),query(l-1));
}
} vals;
vector<int> graph[N];
int fa[N],son[N],size[N],dep[N];
int id,dfn[N],top[N],bottom[N];
int rnk[N];
void dfs1(int s,int from) {
fa[s]=from;
size[s]=1;
dep[s]=dep[from]+1;
for(int ed: graph[s]) {
if(ed==from) continue;
dfs1(ed,s);
size[s]+=size[ed];
if(size[ed]>size[son[s]]) son[s]=ed;
}
}
void dfs2(int s,int currtop) {
top[s]=currtop;
dfn[s]=++id;
bottom[s]=dfn[s];
rnk[id]=s;
if(!son[s]) return;
dfs2(son[s],currtop);
int last=son[s];
for(int ed: graph[s]) {
if(ed==fa[s]||ed==son[s]) continue;
dfs2(ed,ed);
last=ed;
}
bottom[s]=bottom[last];
}
void add1(int x,int y,ll v) {
while(top[x]!=top[y]) {
if(dep[top[x]]>dep[top[y]]) swap(x,y);
vals.add(dfn[top[y]],dfn[y],v);
y=fa[top[y]];
}
if(dep[top[x]]>dep[top[y]]) swap(x,y);
vals.add(dfn[x],dfn[y],v);
}
void add2(int x,ll v) {
vals.add(dfn[x],bottom[x],v);
}
ll query1(int x,int y) {
ll res=0;
while(top[x]!=top[y]) {
if(dep[top[x]]>dep[top[y]]) swap(x,y);
res=ADD(res,vals.query(dfn[top[y]],dfn[y]));
y=fa[top[y]];
}
if(dep[top[x]]>dep[top[y]]) swap(x,y);
res=ADD(res,vals.query(dfn[x],dfn[y]));
return res;
}
ll query2(int x) {
return vals.query(dfn[x],bottom[x]);
}
ll v[N];
void solve() {
int n,m,r,p;
cin>>n>>m>>r>>mod;
for(int i=1;i<=n;++i) {
cin>>v[i];
}
for(int i=1;i<n;++i) {
int u,v;
cin>>u>>v;
graph[u].eb_(v);
graph[v].eb_(u);
}
dfs1(r,0);
dfs2(r,r);
vals.d1.n=n;
vals.d2.n=n;
for(int i=1;i<=n;++i) {
vals.add(dfn[i],v[i]);
}
for(int i=1;i<=m;++i) {
int op,x,y;
ll z;
cin>>op;
switch(op) {
case 1:
cin>>x>>y>>z;
add1(x,y,z);
break;
case 2:
cin>>x>>y;
cout<<query1(x,y)<<'\n';
break;
case 3:
cin>>x>>z;
add2(x,z);
break;
case 4:
cin>>x;
cout<<query2(x)<<'\n';
break;
default:
break;
}
}
}
}
int main() {
ios::sync_with_stdio(0); cin.tie(0);
int T=1;
// cin>>T;
while(T--) {
Solution::solve();
}
return 0;
}
by M1saka16I72 @ 2024-07-16 18:57:52
会这么多科技/bx