1 #include<cstdio>
2 #include<iostream>
3 #include<vector>
4 #define tx top[x]
5 #define ty top[y]
6 #define ls o<<1
7 #define rs o<<1|1
8 #define M ((L+R)>>1)
9 using namespace std;
10 const int maxn = 100010;
11
12 int n, m, P ,root, tot;
13 int A[maxn], fa[maxn], deep[maxn], num[maxn], son[maxn], ID[maxn], top[maxn], fID[maxn];
14 int sumv[maxn*4],addv[maxn*4];
15 vector<int> G[maxn];
16
17 void addedge(int x,int y) {
18 G[x].push_back(y);
19 }
20
21 int dfs1(int x,int dep) { //返回包括自己,子树的大小
22 deep[x] = dep;
23 int ret = 1;
24 int len = G[x].size();
25 int MX = 0;
26 for(int i = 0;i < len;i++) {
27 int tp = G[x][i];
28 if(fa[x] == tp) continue;
29 fa[tp] = x;
30 int back = dfs1(tp,dep+1);
31 if(back > MX) {
32 son[x] = tp;
33 MX = back;
34 }
35 ret += back;
36 }
37 num[x] = ret;
38 return ret;
39 }
40
41 void dfs2(int x) {
42 if(x == 0) return;
43 ID[x] = ++tot;
44 fID[tot] = x;
45 if(son[fa[x]] == x) top[x] = top[fa[x]];
46 else top[x] = x;
47 int len = G[x].size();
48 dfs2(son[x]);
49 for(int i = 0;i < len;i++) {
50 int tp = G[x][i];
51 if(tp != fa[x] && tp != son[x]) dfs2(tp);
52 }
53 }
54
55 inline void build(int o,int L,int R) {
56 if(L == R) {
57 sumv[o] = A[fID[L]]%P;
58 return;
59 }
60 build(ls,L,M);
61 build(rs,M+1,R);
62 sumv[o] = (sumv[ls] + sumv[rs])%P;
63 }
64
65 inline void pushdown(int o,int L,int R) {
66 (addv[ls] += addv[o])%=P;
67 (addv[rs] += addv[o])%=P;
68 (sumv[ls] += addv[o]*(M-L+1))%=P;
69 (sumv[rs] += addv[o]*(R-M))%=P;
70 addv[o] = 0;
71 }
72
73 int ql,qr,qa;
74 inline void update(int o,int L,int R) {
75 if(ql <= L && R <= qr) {
76 (addv[o] += qa)%=P;
77 (sumv[o] += qa*(R-L+1))%=P;
78 return;
79 }
80 pushdown(o,L,R);
81 if(ql <= M) update(ls,L,M);
82 if(qr > M) update(rs,M+1,R);
83 sumv[o] = (sumv[ls] + sumv[rs])%P;
84 }
85
86 inline int query(int o,int L,int R) {
87 if(ql <= L && R <= qr) return sumv[o]%P;
88 int ret = 0;
89 pushdown(o,L,R);
90 if(ql <= M) (ret += query(ls,L,M))%=P;
91 if(qr > M) (ret += query(rs,M+1,R))%=P;
92 return ret%P;
93 }
94
95
96 int LCA(int x,int y) {
97 int ret = 0;
98 while(tx != ty) {
99 if(deep[tx] >= deep[ty]) {
100 //x 走到 top[x](编号小) 的 爸爸 ,top[x] 的爸爸是轻链
101 ql = ID[tx], qr = ID[x];//下闭上开
102 (ret += query(1,1,n))%=P;
103 x = fa[tx];
104 }
105 else {
106 ql = ID[ty], qr = ID[y];
107 (ret += query(1,1,n))%=P;
108 y = fa[ty];
109 }
110 }
111
112 if(x == y) {
113 ql = ID[x],qr = ql;
114 (ret += query(1,1,n))%=P;
115 return ret;
116 }
117 if(deep[x] > deep[y]) swap(x,y);
118 ql = ID[x], qr = ID[y];
119 (ret += query(1,1,n))%=P;
120 return ret;
121 }
122
123 void LCA_add(int x,int y,int k) {
124 qa = k%P;
125 while(tx != ty) {
126 if(deep[tx] >= deep[ty]) {
127 //x 走到 top[x](编号小) 的 爸爸 ,top[x] 的爸爸是轻链
128 ql = ID[tx], qr = ID[x];//下闭上开
129 update(1,1,n);
130 x = fa[tx];
131 }
132 else {
133 ql = ID[ty], qr = ID[y];
134 update(1,1,n);
135 y = fa[ty];
136 }
137 }
138
139 if(x == y) {
140 ql = ID[x],qr = ql;
141 update(1,1,n);
142 return;
143 }
144 if(deep[x] > deep[y]) swap(x,y);
145 ql = ID[x], qr = ID[y];
146 update(1,1,n);
147 }
148
149 int main() {
150 scanf("%d %d %d %d",&n, &m, &root, &P);
151 for(int i = 1;i <= n;i++) scanf("%d",A+i);
152 for(int i = 1,x,y;i < n;i++) {
153 scanf("%d%d",&x,&y);
154 addedge(x,y);
155 addedge(y,x);
156 }
157
158 dfs1(root,1);
159 dfs2(root);
160 build(1,1,n);
161
162 for(int i = 1,x,l,r,z;i <= m;i++) {
163 scanf("%d",&x);
164 if(x == 1) {
165 scanf("%d%d%d",&l,&r,&z);
166 LCA_add(l,r,z);
167 } else if(x == 2) {
168 scanf("%d%d",&l,&r);
169 printf("%d\n",LCA(l,r));
170 } else if(x == 3) {
171 scanf("%d%d",&l,&z);
172 ql = ID[l],qr = ql+num[l]-1,qa=z;
173 update(1,1,n);
174 } else {
175 scanf("%d",&z);
176 ql = ID[z],qr = ql + num[z]-1;
177 printf("%d\n",query(1,1,n));
178 }
179 }
180 return 0;
181 }