rt,写的是树链剖分,求观感
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxi=1e5+9;
struct node{
vector<int> e;
int d,siz,son,f,top,v,id;
}trr[maxi];
struct segment_tree{
ll sum,laz;
int s,t,m;
}sgt[maxi<<2];
ll P;
int N,M,rt,L,R,D,cnt,a[maxi];
#define now trr[p]
#define mxsn trr[trr[p].son]
#define to trr[i]
void dfs1(int p){
now.siz=1;
for(int i:now.e){
if(i!=now.f){
to.f=p,to.d=now.d+1;
dfs1(i);
now.siz+=to.siz;
if(mxsn.siz<to.siz){
now.son=i;
}
}
}
return;
}
void dfs2(int p){
cnt++;
//cerr<<"p="<<p
// <<",cnt="<<cnt
// <<'\n';
now.id=cnt;
a[cnt]=now.v;
if(now.siz==1)return;
mxsn.top=now.top;
dfs2(now.son);
for(int i:now.e){
if(i==now.f||i==now.son)continue;
to.top=i;
dfs2(i);
}
return;
}
#define _ls p<<1
#define _rs p<<1|1
#define now sgt[p]
#define ls sgt[_ls]
#define rs sgt[_rs]
inline ll mod(ll a){return a%P;}
inline void update(int p){
now.sum=mod(ls.sum+rs.sum);
}
inline void pushdown(int p){
if(now.laz){
ls.sum=mod(ls.sum+now.laz*(ls.t-ls.s+1));
rs.sum=mod(rs.sum+now.laz*(rs.t-rs.s+1));
ls.laz=mod(ls.laz+now.laz);
rs.laz=mod(rs.laz+now.laz);
now.laz=0;
}
return;
}
//inline void look(int p){
//cerr<<"p="<<p
// <<",s="<<now.s
// <<",t="<<now.t
// <<",sum="<<now.sum
// <<'\n';
//}
//void test(int p){
// look(p);
// if(now.s==now.t)return;
// pushdown(p);
// test(_ls),test(_rs);
// update(p);
// return;
//}
void build(int s,int t,int p){
now.s=s,now.t=t,now.m=(s+t)>>1;
if(s==t){
now.sum=1ll*a[s]%P;
//look(p);
return;
}
build(s,now.m,_ls),build(now.m+1,t,_rs);
update(p);
//look(p);
return;
}
void wt(int p){
if(L<=now.s&&now.t<=R){
now.sum+=1ll*D*(now.t-now.s+1)%P;
now.laz=mod(now.laz+1ll*D);
return;
}
pushdown(p);
if(L<=now.m)wt(_ls);
if(now.m<R)wt(_rs);
update(p);
return;
}
ll rd(int p){
if(L<=now.s&&now.t<=R)return now.sum;
ll ans=0;
pushdown(p);
if(L<=now.m)ans=mod(ans+rd(_ls));
if(now.m<R)ans=mod(ans+rd(_rs));
update(p);
return ans;
}
#define nowx trr[x]
#define nowy trr[y]
#define topx trr[nowx.top]
#define topy trr[nowy.top]
inline void _1(int x,int y,int z){
D=z;
if(nowx.top!=nowy.top){
for(;nowx.top!=nowy.top;){
if(topx.d>topy.d)swap(x,y);
L=topy.id,R=nowy.id;wt(1);
y=topy.f;
}
}
if(nowx.d>nowy.d)swap(x,y);
L=nowx.id,R=nowy.id;wt(1);
return;
}
inline ll _2(int x,int y){
ll ans=0;
if(trr[x].top!=trr[y].top){
for(;nowx.top!=nowy.top;){
if(topx.d>topy.d)swap(x,y);
L=topy.id,R=nowy.id;
ans=mod(ans+rd(1));
y=topy.f;
}
}
if(nowx.d>nowy.d)swap(x,y);
L=nowx.id,R=nowy.id;ans=mod(ans+rd(1));
return ans;
}
inline void _3(int x,int z){
//cerr<<"x="<<x<<",z="<<z<<'\n';
L=nowx.id,R=L+nowx.siz-1,D=z;
//cerr<<"L="<<L
// <<",R="<<R
// <<",D="<<D
// <<",id="<<nowx.id
// <<'\n';
wt(1);
return;
}
inline ll _4(int x){
L=nowx.id,R=L+nowx.siz-1;
return mod(rd(1));
}
int main(){
cin>>N>>M>>rt>>P;
for(int i=1;i<=N;i++)scanf("%d",&trr[i].v);
for(int i=1,u,v;i<N;i++){
scanf("%d%d",&u,&v);
trr[u].e.push_back(v);
trr[v].e.push_back(u);
}
trr[rt].d=1,trr[rt].top=rt;
dfs1(rt);
dfs2(rt);
//for(int i=1;i<=N;i++)cerr<<to.id<<' ';cerr<<'\n';
build(1,N,1);
//test(1);
for(int i=1,op,x,y,z;i<=M;i++){
scanf("%d%d",&op,&x);
if(op==1){
scanf("%d%d",&y,&z);
_1(x,y,z);
}
if(op==2){
scanf("%d",&y);
printf("%lld\n",_2(x,y));
}
if(op==3){
scanf("%d",&z);
//cerr<<"x="<<x<<",z="<<z<<'\n';
_3(x,z);
}
if(op==4)printf("%lld\n",_4(x));
}
return 0;
}