| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 
 | #include<bits/stdc++.h>using namespace std;
 inline int read(){
 int x=0,w=0;char c=getchar();
 while(!isdigit(c)) w|=c=='-',c=getchar();
 while(isdigit(c)) x=x*10+c-'0',c=getchar();
 return w?-x:x;
 }
 namespace star
 {
 const int maxn=1e5+10,maxm=1e5+10;
 int n,m,root,mod;
 int fa[maxn],dep[maxn],son[maxn],siz[maxn],top[maxn],dfn[maxn],a[maxn],w[maxn];
 int ecnt,head[maxn],to[maxn<<1],nxt[maxn<<1];
 inline void addedge(int a,int b){
 to[++ecnt]=b,nxt[ecnt]=head[a],head[a]=ecnt;
 to[++ecnt]=a,nxt[ecnt]=head[b],head[b]=ecnt;
 }
 struct SegmentTree{
 #define ls (ro<<1)
 #define rs (ro<<1|1)
 #define mid ((l+r)>>1)
 int val[maxn<<2],tag[maxn<<2];
 inline void pushup(int ro){val[ro]=(val[ls]+val[rs])%mod;}
 inline void pushdown(int ro,int l,int r){
 tag[ls]+=tag[ro],val[ls]=(val[ls]+(mid-l+1)*tag[ro])%mod;
 tag[rs]+=tag[ro],val[rs]=(val[rs]+(r-mid)*tag[ro])%mod;
 tag[ro]=0;
 }
 void build(const int &ro=1,const int &l=1,const int &r=n){
 if(l==r) return val[ro]=w[l]%mod,void();
 build(ls,l,mid),build(rs,mid+1,r);
 pushup(ro);
 }
 void update(int x,int y,int k,const int &ro=1,const int &l=1,const int &r=n){
 if(x==l and y==r) return tag[ro]+=k,val[ro]=(val[ro]+k*(r-l+1))%mod,void();
 if(tag[ro]) pushdown(ro,l,r);
 if(y<=mid) update(x,y,k,ls,l,mid);
 else if(x>mid) update(x,y,k,rs,mid+1,r);
 else update(x,mid,k,ls,l,mid),update(mid+1,y,k,rs,mid+1,r);
 pushup(ro);
 }
 int query(int x,int y,const int &ro=1,const int &l=1,const int &r=n){
 if(x==l and y==r) return val[ro];
 if(tag[ro]) pushdown(ro,l,r);
 if(y<=mid) return query(x,y,ls,l,mid);
 if(x>mid) return query(x,y,rs,mid+1,r);
 return (query(x,mid,ls,l,mid)+query(mid+1,y,rs,mid+1,r))%mod;
 }
 #undef ls
 #undef rs
 #undef mid
 }st;
 void dfs1(int x,int Fa){
 fa[x]=Fa,siz[x]=1,dep[x]=dep[Fa]+1;
 int mx=-1;
 for(int u,i=head[x];i;i=nxt[i]) if((u=to[i])!=Fa){
 dfs1(u,x);
 siz[x]+=siz[u];
 if(siz[u]>mx) son[x]=u,mx=siz[u];
 }
 }
 void dfs2(int x,int topf){
 w[dfn[x]=++dfn[0]]=a[x];
 top[x]=topf;
 if(!son[x]) return;
 dfs2(son[x],topf);
 for(int u,i=head[x];i;i=nxt[i]) if((u=to[i])!=fa[x] and u!=son[x]) dfs2(u,u);
 }
 inline void update(int x,int y,int k){
 while(top[x]!=top[y]){
 if(dep[top[x]]<dep[top[y]]) swap(x,y);
 st.update(dfn[top[x]],dfn[x],k);
 x=fa[top[x]];
 }
 if(dep[x]>dep[y])swap(x,y);
 st.update(dfn[x],dfn[y],k);
 }
 inline int 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+st.query(dfn[top[x]],dfn[x]))%mod;
 x=fa[top[x]];
 }
 if(dep[x]>dep[y])swap(x,y);
 ans=(ans+st.query(dfn[x],dfn[y]))%mod;
 return ans;
 }
 inline void work(){
 n=read(),m=read(),root=read(),mod=read();
 for(int i=1;i<=n;i++) a[i]=read();
 for(int i=1;i<n;i++) addedge(read(),read());
 dfs1(root,root),dfs2(root,root);
 st.build();
 while(m--){
 int a,b,c;
 switch(read()){
 case 1:{
 a=read(),b=read(),c=read()%mod;
 update(a,b,c);
 break;
 }
 case 2:{
 printf("%d\n",query(read(),read()));
 break;
 }
 case 3:{
 a=read(),b=read();
 st.update(dfn[a],dfn[a]+siz[a]-1,b);
 break;
 }
 case 4:{
 a=read();
 printf("%d\n",st.query(dfn[a],dfn[a]+siz[a]-1));
 break;
 }
 }
 }
 }
 }
 signed main(){
 star::work();
 return 0;
 }
 
 |