#include<bits/stdc++.h>
using namespace std;
const int N=100002;
#define up(t) tr[t]=(tr[t<<1]+tr[t<<1|1])%M;
#define mid ((l+r)>>1)
struct node{
int to,ne;
}e[N<<1];
int son[N],top[N],tr[N<<2],w[N],wt[N],id[N],la[N<<2],tot,h[N],fa[N],x,y,z,M,r,dep[N],n,siz[N],cnt,m,i,opt;
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
int x=0,fl=1;char ch=gc();
for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
return x*fl;
}
inline void wri(int a){if(a>=10)wri(a/10);putchar(a%10|48);}
inline void wln(int a){if(a<0)a=-a,putchar('-');wri(a);puts("");}
void add(int x,int y){
e[++tot]=(node){y,h[x]};
h[x]=tot;
}
void build(int t,int l,int r){
if (l==r){
tr[t]=wt[l];
return;
}
build(t<<1,l,mid);
build(t<<1|1,mid+1,r);
up(t);
}
void down(int t,int l,int r){
if (la[t]){
la[t<<1]+=la[t];
la[t<<1|1]+=la[t];
(tr[t<<1]+=(mid-l+1)*la[t])%=M;
(tr[t<<1|1]+=(r-mid)*la[t])%=M;
la[t]=0;
}
}
void update(int t,int l,int r,int x,int y,int z){
if (x<=l && r<=y){
tr[t]+=z*(r-l+1);
la[t]+=z;
return;
}
down(t,l,r);
if (x<=mid) update(t<<1,l,mid,x,y,z);
if (mid<y) update(t<<1|1,mid+1,r,x,y,z);
up(t);
}
int query(int t,int l,int r,int x,int y){
if (x<=l && r<=y) return tr[t];
down(t,l,r);
int sum=0;
if (x<=mid) sum+=query(t<<1,l,mid,x,y);
if (mid<y) sum+=query(t<<1|1,mid+1,r,x,y);
return sum%M;
}
void uprange(int x,int y,int z){
z%=M;
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swap(x,y);
update(1,1,n,id[top[x]],id[x],z);
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
update(1,1,n,id[x],id[y],z);
}
int qrange(int x,int y){
int ans=0;
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swap(x,y);
(ans+=query(1,1,n,id[top[x]],id[x]))%=M;
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
(ans+=query(1,1,n,id[x],id[y]))%=M;
return ans;
}
void upson(int x,int z){
update(1,1,n,id[x],id[x]+siz[x]-1,z);
}
int qson(int x){
return query(1,1,n,id[x],id[x]+siz[x]-1);
}
void dfs1(int u,int f,int de){
fa[u]=f;dep[u]=de;siz[u]=1;
int mx=-1;
for (int i=h[u],v;i;i=e[i].ne)
if ((v=e[i].to)!=f){
dfs1(v,u,de+1);
siz[u]+=siz[v];
if (siz[v]>mx) mx=siz[v],son[u]=v;
}
}
void dfs2(int u,int topf){
id[u]=++cnt;
wt[cnt]=w[u];
top[u]=topf;
if (!son[u]) return;
dfs2(son[u],topf);
for (int i=h[u],v;i;i=e[i].ne)
if ((v=e[i].to)!=fa[u] && v!=son[u]) dfs2(v,v);
}
int main(){
n=read();m=read();r=read();M=read();
for (i=1;i<=n;i++) w[i]=read();
for (i=1;i<n;i++){
x=read();y=read();
add(x,y);add(y,x);
}
dfs1(r,0,1);
dfs2(r,r);
build(1,1,n);
while (m--){
opt=read();x=read();
if (opt==1){
y=read();z=read();
uprange(x,y,z);
}
if (opt==2){
y=read();
wln(qrange(x,y));
}
if (opt==3){
z=read();
upson(x,z);
}
if (opt==4) wln(qson(x));
}
}
洛谷P3384 【模板】树链剖分
最新推荐文章于 2022-10-25 15:21:16 发布