kisuti @ 2023-11-09 10:24:37
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
int x=0;
char ch=getchar();
bool flag=true;
while(!isdigit(ch)){
if(ch=='-')flag=false;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
if(flag)return x;
return ~(x-1);
}
long long n,m,r,p,cnt=0,idx=0;
long long res=0;
int fa[200010],e[200010],ne[200010],h[200010];
long long si[200010],dep[200010],son[200010],w[200010],wt[200010],top[200010],id[200010];
struct node{
long long val,tag;
int sz;
}shu[4000010];
void update(int id){shu[id].val=(shu[id<<1].val%p+shu[id<<1|1].val%p)%p;}
void build(int id,int l,int r){
shu[id].sz=r-l+1;
shu[id].tag=0;
if(l==r)shu[id].val=wt[l]%p;
else{
int mid=(l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
update(id);
}
}
void settag(int id,int tag){
shu[id].val+=tag*shu[id].sz%p;
shu[id].tag+=tag;
shu[id].val=shu[id].val%p;
}
void pushdown(int id){
settag(id<<1,shu[id].tag);
settag(id<<1|1,shu[id].tag);
shu[id].tag=0;
}
void mutify(int id,int l,int r,int ql,int qr,int k){
if(ql==l&&qr==r){
settag(id,k);
return;
}
pushdown(id);
int mid=(l+r)>>1;
if(qr<=mid)mutify(id<<1,l,mid,ql,qr,k);
else if(ql>mid)mutify(id<<1|1,mid+1,r,ql,qr,k);
else {
mutify(id<<1,l,mid,ql,mid,k);
mutify(id<<1|1,mid+1,r,mid+1,qr,k);
}
update(id);
}
long long que(int id,int l,int r,int ql,int qr){
if(l==ql&&r==qr)return shu[id].val%p;
pushdown(id);
int mid=(l+r)>>1;
if(qr<=mid)return que(id<<1,l,mid,ql,qr)%p;
else if(ql>mid)return que(id<<1|1,mid+1,r,ql,qr)%p;
else return (que(id<<1,l,mid,ql,mid)%p+que(id<<1|1,mid+1,r,mid+1,qr)%p)%p;
}
void add(int a, int b){e[++idx] = b, ne[idx] = h[a], h[a] = idx ;}
void dfs1(int u,int z,int d){
fa[u]=z,dep[u]=d,si[u]=1;
for(int i=h[i];i;i=ne[i]){
int o=e[i];
if(o==z)continue;
dfs1(o,u,d+1);
si[u]+=si[o];
if(si[o]>si[son[u]])son[u]=o;
}
}
void dfs2(int u,int topf){
id[u]=++cnt;
wt[cnt]=w[u]%p;
top[u]=topf;
if(!son[u])return;
dfs2(son[u],topf);
for(int i=h[u];i;i=ne[i]){
int o=e[i];
if(o==son[u]||o==fa[u])continue;
dfs2(o,o);
}
}
void update_path(int x,int y,int z){
z%=p;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
mutify(1,1,n,id[top[x]],id[x],z);
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
mutify(1,1,n,id[x],id[y],z);
}
long long que_path(int x,int y){
res=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
res=(res%p+que(1,1,n,id[top[x]],id[x])%p)%p;
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
res=(res%p+que(1,1,n,id[x],id[y])%p)%p;
return res%p;
}
void update_tree(int x,int k){
mutify(1,1,n,id[x],id[x]+si[x]-1,k);
}
long long que_tree(int x){
res=que(1,1,n,id[x],id[x]+si[x]-1)%p;
return res;
}
int main(){
n=rd(),m=rd(),r=rd(),p=rd();
for(int i=1;i<=n;i++){w[i]=rd();}
for(int i=1;i<=n-1;i++){
int x=rd(),y=rd();
add(x,y);
add(y,x);
}
dfs1(r,0,1);
dfs2(r,r);
build(1,1,n);
while(m--){
int opt=rd();
if(opt==1){
int x=rd(),y=rd(),z=rd();
update_path(x,y,z);
}
if(opt==2){
int x=rd(),y=rd();
printf("%d\n",que_path(x,y));
}
if(opt==3){
int x=rd(),z=rd();
update_tree(x,z);
}
if(opt==4){
int x=rd();
printf("%d\n",que_tree(x));
}
}
return 0;
}
by xhQYm @ 2023-11-09 11:24:16
看成了0-1trie。。。
by kisuti @ 2023-11-09 19:13:42
。。。