1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5
6 using namespace std;
7
8 const int maxn=4e6+10;
9 struct node//±ß
10 {
11 int to;
12 int next;
13 }way[maxn];
14 struct tree//Ï߶ÎÊ÷
15 {
16 int l,r,ls,rs;
17 int sum;
18 int lazy;
19 }tree[maxn];
20 int head[maxn];
21 int value[maxn];
22 int top[maxn];
23 int deep[maxn];
24 int parents[maxn];
25 int son[maxn];
26 int size[maxn];
27 int mod;
28 int tot;
29 int rt;
30 int n,m,r;
31 int jd[maxn];
32 int dfsx[maxn];
33
34 int add(int x,int y)
35 {
36 way[++tot].next=head[x];
37 way[tot].to=y;
38 head[x]=tot;
39 }
40
41 int dfs1(int x)
42 {
43 deep[x]=deep[parents[x]]+1;
44 size[x]=1;
45 for(int i=head[x];i;i=way[i].next)
46 {
47 int to=way[i].to;
48 if(to!=parents[x])
49 {
50 parents[to]=x;
51 dfs1(to);
52 size[x]+=size[to];
53 if(size[to]>size[son[x]])
54 {
55 son[x]=to;
56 }
57 }
58 }
59
60 }
61
62 int dfs2(int x,int t)
63 {
64 top[x]=t;
65 dfsx[x]=++tot;
66 jd[tot]=x;
67 if(son[x])
68 {
69 dfs2(son[x],t);
70 }
71 for(int i=head[x];i;i=way[i].next)
72 {
73 int to=way[i].to;
74 if(to!=parents[x]&&to!=son[x])
75 {
76 dfs2(to,to);
77 }
78 }
79 }
80
81 int len(int x)
82 {
83 return tree[x].r-tree[x].l+1;
84 }
85
86 inline int pushup(int x)
87 {
88 tree[x].sum=(tree[tree[x].ls].sum+tree[tree[x].rs].sum)%mod;
89 }
90
91 inline int pushdown(int x)
92 {
93 if(tree[x].lazy)
94 {
95 int ls=tree[x].ls;
96 int rs=tree[x].rs;
97 int lz=tree[x].lazy;
98 tree[ls].lazy=(tree[ls].lazy+lz)%mod;
99 tree[rs].lazy=(tree[rs].lazy+lz)%mod;
100 tree[ls].sum=(tree[ls].sum+lz*len(ls))%mod;
101 tree[rs].sum=(tree[rs].sum+lz*len(rs))%mod;
102 tree[x].lazy=0;
103 }
104 }
105
106 void build(int l,int r,int x)
107 {
108 if(l==r)
109 {
110 tree[x].sum=value[jd[l]];
111 tree[x].l=tree[x].r=l;
112 return ;
113 }
114 int mid=(l+r)>>1;
115 tree[x].ls=tot++;
116 tree[x].rs=tot++;
117 build(l,mid,tree[x].ls);
118 build(mid+1,r,tree[x].rs);
119 tree[x].l=tree[tree[x].ls].l;
120 tree[x].r=tree[tree[x].rs].r;
121 pushup(x);
122 }
123
124 void jia(int l,int r,int c,int x)
125 {
126 if(tree[x].l>=l&&tree[x].r<=r)
127 {
128 tree[x].lazy=(tree[x].lazy+c)%mod;
129 tree[x].sum=(tree[x].sum+c*len(x))%mod;
130 return ;
131 }
132 pushdown(x);
133 int mid=(tree[x].l+tree[x].r)>>1;
134 if(mid>=l)
135 {
136 jia(l,r,c,tree[x].ls);
137 }
138 if(mid<r)
139 {
140 jia(l,r,c,tree[x].rs);
141 }
142 pushup(x);
143 }
144
145 int he(int l,int r,int x)
146 {
147 if(tree[x].l>=l&&tree[x].r<=r)
148 {
149 return tree[x].sum;
150 }
151 pushdown(x);
152 int mid=(tree[x].l+tree[x].r)>>1;
153 int ans=0;
154 if(mid>=l)
155 {
156 ans+=he(l,r,tree[x].ls);
157 }
158 if(mid<r)
159 {
160 ans+=he(l,r,tree[x].rs);
161 }
162 return ans%mod;
163 }
164
165 int ask(int x,int y)
166 {
167 int res=0;
168 while(top[x]!=top[y])
169 {
170 if(deep[top[x]]<deep[top[y]])
171 swap(x,y);
172 res=(res+he(dfsx[top[x]],dfsx[x],rt))%mod;
173 x=parents[top[x]];
174 }
175 if(dfsx[x]>dfsx[y])
176 swap(x,y);
177 res=(res+he(dfsx[x],dfsx[y],rt))%mod;
178 return res;
179 }
180
181 int jias(int x,int y,int c)
182 {
183 while(top[x]!=top[y])
184 {
185 if(deep[top[x]]<deep[top[y]])
186 swap(x,y);
187 jia(dfsx[top[x]],dfsx[x],c,rt);
188 x=parents[top[x]];
189 }
190 if(dfsx[x]>dfsx[y])
191 swap(x,y);
192 jia(dfsx[x],dfsx[y],c,rt);
193 }
194 int main()
195 {
196 //freopen("ww.out","w",stdout);
197 scanf("%d %d %d %d",&n,&m,&r,&mod);
198 for(int i=1;i<=n;i++)
199 {
200 scanf("%d",&value[i]);
201 }
202 for(int i=1;i<=n-1;i++)
203 {
204 int x,y;
205 scanf("%d %d",&x,&y);
206 add(x,y);
207 add(y,x);;
208 }
209 tot=0;
210 dfs1(r);
211 dfs2(r,r);
212 tot=0;
213 build(1,n,rt=tot++);
214 for(int i=1;i<=m;i++)
215 {
216 int flag;
217 int x,y,z;
218 scanf("%d",&flag);
219 if(flag==1)
220 {
221 scanf("%d %d %d",&x,&y,&z);
222 jias(x,y,z);
223 }
224 else
225 if(flag==2)
226 {
227
228 scanf("%d %d",&x,&y);
229 int ans=ask(x,y);
230 printf("%d\n",ans);
231 }
232 else
233 if(flag==3)
234 {
235 scanf("%d %d",&x,&y);
236 jia(dfsx[x],dfsx[x]+size[x]-1,y,rt);
237 }
238 else
239 if(flag==4)
240 {
241 scanf("%d",&x);
242 int ans=he(dfsx[x],dfsx[x]+size[x]-1,rt);
243 printf("%d\n",ans);
244 }
245 }
246
247 return 0;
248 }