退役菜鸡Oier(轻喷)、 调废了已经 (看来数据结构不适合我QAQ,CUP,线段树3一生之敌---“抄”题解也调不了))
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 2e6+9;
int u[N],v[N],root[N],to[N],cnt;
int id[N],a[N],top[N],size[N],fa[N];
int val[N],son[N],dep[N];
int n,m,R,p,idex;
inline int read()
{
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0',c=getchar();}
return x*f;
}
inline int lson(int x)
{
return x<<1;
}
inline int rson(int x)
{
return x<<1|1;
}
struct stu
{
int sum;
int lazy;
int size;
}tree[N*4];
void add_edge(int a,int b)
{
cnt++;
u[cnt] = a;
v[cnt] = b;
to[cnt] = root[a];
root[a] = cnt;
return;
}
void update(int x)
{
tree[x].sum = (tree[lson(x)].sum + tree[rson(x)].sum + p)%p;
return;
}
void down(int x)
{
tree[lson(x)].lazy = (tree[lson(x)].lazy+tree[x].lazy+p)%p;
tree[rson(x)].lazy = (tree[rson(x)].lazy+tree[x].lazy+p)%p;
tree[lson(x)].sum = (tree[lson(x)].sum+tree[x].lazy*tree[lson(x)].size+p)%p;
tree[rson(x)].sum = (tree[rson(x)].sum+tree[x].lazy*tree[rson(x)].size+p)%p;
tree[x].lazy = 0;
return;
}
int dfs1(int x,int father)
{
dep[x] = dep[father] + 1;
fa[x] = father;
size[x] = 1;
int maxx = -1;
for(int i=root[x];i;i=to[i])
{
if(v[i] == father) continue;
size[x] += dfs1(v[i],x);
if(maxx<size[v[i]])
{
maxx = size[v[i]];
son[x] = v[i];
}
}
return size[x];
}
void dfs2(int x,int topf)
{
top[x] = topf;
id[x] = ++idex;
a[idex] = val[x]%p;
if(!son[x]) return;
dfs2(son[x],topf);
for(int i=root[x];i;i=to[i])
{
if(v[i] == son[x] || v[i] == fa[x]) continue;
dfs2(v[i],v[i]);
}
return;
}
void build(int x,int l,int r)
{
tree[x].size = r-l+1;
if(l==r)
{
tree[x].sum = a[l]%p;
return;
}
int mid = (l+r)>>1;
build(lson(x),l,mid);
build(rson(x),mid+1,r);
update(x);
return;
}
int sum(int x,int sl,int sr,int l,int r)
{
if(l<=sl && sr<=r) return tree[x].sum%p;
int mid = (sl+sr)>>1;
int ans = 0;
down(x);
if(l<=mid) ans = (ans+sum(lson(x),sl,mid,l,r)+p)%p;
if(r>mid) ans = (ans+sum(rson(x),mid+1,sr,l,r)+p)%p;
update(x);
return ans%p;
}
void add(int x,int sl,int sr,int l,int r,int k)
{
if(l<=sl && sr<=r)
{
tree[x].sum = (tree[x].sum+tree[x].size*k%p + p)%p;
tree[x].lazy = (tree[x].lazy+k)%p;
return;
}
int mid=(sl+sr)>>1;
down(x);
if(l<=mid) add(lson(x),sl,mid,l,r,k);
if(r>mid) add(rson(x),mid+1,sr,l,r,k);
update(x);
return;
}
int ask_line(int a,int b)
{
int ans = 0;
while(top[a]!=top[b])
{
if(dep[a]<dep[b]) swap(a,b);
ans = (ans + sum(1,1,n,id[top[a]],id[a])%p)%p;
a = fa[top[a]];
}
if(dep[a]<dep[b]) swap(a,b);
ans = (ans + sum(1,1,n,id[b],id[a])%p)%p;
return ans%p;
}
void add_line(int a,int b,int k)
{
while(top[a]!=top[b])
{
if(dep[a]<dep[b]) swap(a,b);
add(1,1,n,id[top[a]],id[a],k);
a = fa[top[a]];
}
if(dep[a]<dep[b]) swap(a,b);
add(1,1,n,id[b],id[a],k);
return;
}
int ask_tree(int x)
{
return sum(1,1,n,id[x],id[x]+size[x]-1)%p;
}
void add_tree(int x,int k)
{
add(1,1,n,id[x],id[x]+size[x]-1,k);
return;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&R,&p);
for(int i=1;i<=n;i++) val[i]=read();
for(int i=1;i<=n-1;i++)
{
int a,b;
a=read();b=read();
add_edge(a,b);
add_edge(b,a);
}
dfs1(R,R);
dfs2(R,R);
build(1,1,n);
for(int i=1;i<=m;i++)
{
int rep,a,b,c;
rep = read();
if(rep == 1)
{
a=read();b=read();c=read();
c%=p;
add_line(a,b,c);
}
if(rep == 2)
{
a=read();b=read();
printf("%d\n",ask_line(a,b)%p);
}
if(rep == 3)
{
a=read();b=read();
b%=p;
add_tree(a,b);
}
if(rep == 4)
{
a=read();
printf("%d\n",ask_tree(a)%p);
}
}
return 0;
}