#include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <cstdlib> #include <vector> #include <iostream> #define lson rt<<1 #define rson rt<<1|1 using namespace std; typedef long long ll; const int maxn=2e5+10; int N,M,R,P; int deep[maxn],F[maxn],size_[maxn],son[maxn];//深度,父亲节点,子树大小,重儿子 vector<int> G[maxn]; void dfs1(int x,int f) { int son_zhong=0,son_num=0; size_[x]=1; for(int i=0;i<G[x].size();i++) { int v=G[x][i]; if(v==f) continue; F[v]=x; deep[v]=deep[x]+1; dfs1(v, x); size_[x]+=size_[v]; if(son_num<size_[v]) { son_num=size_[v]; son_zhong=v; } } son[x]=son_zhong; } int id[maxn],id_inv[maxn],wt[maxn],w[maxn],top[maxn]; int cnt; void dfs2(int x,int topt) { id[x]=++cnt; top[id[x]]=topt; wt[id[x]]=w[x]; if(son[x]!=0) dfs2(son[x], topt); for(int i=0;i<G[x].size();i++) { int v=G[x][i]; if(v==F[x]||v==son[x]) continue; dfs2(v, v); } } //区间查询 区间更新线段树 ll tree[maxn<<2],lazy[maxn<<2]; void pushdown(int rt,int l,int r){ lazy[lson]=(lazy[lson]+lazy[rt])%P; lazy[rson]=(lazy[rson]+lazy[rt])%P; int mid=(l+r)/2; tree[lson]=(tree[lson]+lazy[rt]*(mid-l+1))%P; tree[rson]=(tree[rson]+lazy[rt]*(r-mid))%P; lazy[rt]=0; } void pushup(int rt) { tree[rt]=(tree[lson]+tree[rson])%P; } void build(int rt,int l,int r) { if(l==r) { tree[rt]=wt[l]; return; } int mid=(l+r)/2; build(lson,l,mid); build(rson,mid+1,r); pushup(rt); } void update(int x,int L,int R,int l,int r,int rt) { pushdown(rt, l, r); if(L<=l&&r<=R) { tree[rt]=(tree[rt]+(r-l+1)*x); lazy[rt]=(x)%P; return; } int mid=(l+r)/2; if(mid>=L) update(x, L, R, l,mid,lson); if(mid<R) update(x, L, R, mid+1,r,rson); pushup(rt); } ll query(int L,int R,int l,int r,int rt) { pushdown(rt,l,r); if(L<=l&&r<=R) { return tree[rt]; } int mid=(r+l)/2; ll ans=0; if(mid>=L) ans=(ans+query(L, R, l,mid,lson))%P; if(mid<R) ans=(ans+query(L, R, mid+1,r,rson))%P; return ans; } int main() { cin>>N>>M>>R>>P; for(int i=1;i<=N;i++) cin>>w[i]; for(int i=0;i<N-1;i++) { int u,v; cin>>u>>v; G[u].push_back(v); G[v].push_back(u); } dfs1(R, R); dfs2(R, R); for(int i=1;i<=N;i++) id_inv[id[i]]=i; build(1, 1, N); for(int i=0;i<M;i++) { int flag; cin>>flag; if(flag==1) { int x,y,z; cin>>x>>y>>z; x=id[x]; y=id[y]; while(1) { if(deep[top[x]]<deep[top[y]]) swap(x, y); if(top[x]==top[y]) { if(x<y) swap(x, y); update(z, y, x, 1, N, 1); break; } else { update(z, id[top[x]], x, 1, N, 1); x=id[F[top[x]]]; } } } else if(flag==2) { int x,y; cin>>x>>y; x=id[x]; y=id[y]; ll ans=0; while(1) { if(deep[top[x]]<deep[top[y]]) swap(x, y); if(top[x]==top[y]) { if(x<y) swap(x, y); ans=(ans+query( y, x, 1, N, 1))%P; break; } else { ans=(ans+query(id[top[x]], x, 1, N, 1))%P; x=id[F[top[x]]]; } } cout<<ans<<endl; } else if(flag==3) { int x,z; cin>>x>>z; update(z, id[x], id[x]+size_[x]-1, 1, N, 1); } else if(flag==4) { int x; cin>>x; cout<<query(id[x], id[x]+size_[x]-1, 1, N, 1)<<endl; } } }
来源:https://www.cnblogs.com/King-of-Dark/p/12272926.html