。。。rt。。。安利一发大佬博客https://www.cnblogs.com/ivanovcraft/p/9019090.html
注意:不要把dfn和rw弄混了。。。
#include<cstdio> #include<iostream> #define ll long long #define R register ll #define ls (tr<<1) #define rs (tr<<1|1) const int M=100010; using namespace std; inline ll g() { R ret=0; register char ch; while(!isdigit(ch=getchar())) ; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret; } int n,m,tr,cnt,num,mod; int vr[M<<1],nxt[M<<1],fir[M],dfn[M],pre[M],d[M],sz[M],son[M],top[M],rw[M],w[M]; int tg[M<<2],sum[M<<2]; inline void add(int u,int v) {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;} void dfs(int u) { sz[u]=1; R mx=0; for(R i=fir[u];i;i=nxt[i]) { R v=vr[i]; if(!d[v]) { pre[v]=u; d[v]=d[u]+1; dfs(v); sz[u]+=sz[v]; if(sz[v]>mx) son[u]=v,mx=sz[v]; } } } void dfs_(int u,int tp) { top[u]=tp,dfn[u]=++num,rw[num]=u; if(son[u]) dfs_(son[u],tp); for(R i=fir[u];i;i=nxt[i]) { R v=vr[i]; if(v!=pre[u]&&v!=son[u]) dfs_(v,v); } } inline void build(int tr,int l,int r) { if(l==r) {sum[tr]=w[rw[l]]; if(sum[tr]>=mod) sum[tr]%=mod; return ;} R md=(l+r)>>1; build(ls,l,md),build(rs,md+1,r); sum[tr]=(sum[ls]+sum[rs])%mod; } inline void spread(int tr,int len) { if(tg[tr]) (tg[ls]+=tg[tr])%=mod,(sum[ls]+=(len-(len>>1))*tg[tr])%=mod, (tg[rs]+=tg[tr])%=mod,(sum[rs]+=(len>>1)*tg[tr])%=mod,tg[tr]=0; } inline int query(int tr,int l,int r,int LL,int RR) { R ret=0; if(LL<=l&&r<=RR) {return sum[tr];} spread(tr,r-l+1); R md=(l+r)>>1; if(LL<=md) (ret+=query(ls,l,md,LL,RR))%=mod; if(RR>md) (ret+=query(rs,md+1,r,LL,RR))%=mod; return ret; } inline void update(int tr,int l,int r,int LL,int RR,int inc) { if(LL<=l&&r<=RR) {(tg[tr]+=inc)%=mod,(sum[tr]+=(r-l+1)*inc)%=mod; return ;} spread(tr,r-l+1); R md=(l+r)>>1; if(LL<=md) update(ls,l,md,LL,RR,inc); if(RR>md) update(rs,md+1,r,LL,RR,inc); sum[tr]=(sum[ls]+sum[rs])%mod; } inline void change(int u,int v,int inc) { while(top[u]!=top[v]) { if(d[top[u]]<d[top[v]]) swap(u,v); update(1,1,n,dfn[top[u]],dfn[u],inc); u=pre[top[u]]; } if(dfn[u]>dfn[v]) swap(u,v); update(1,1,n,dfn[u],dfn[v],inc); } inline int qTree(int u,int v) { R ret=0; while(top[u]!=top[v]) { if(d[top[u]]<d[top[v]]) swap(u,v); (ret+=query(1,1,n,dfn[top[u]],dfn[u]))%=mod; u=pre[top[u]]; } if(dfn[u]>dfn[v]) swap(u,v); (ret+=query(1,1,n,dfn[u],dfn[v]))%=mod; return ret; } signed main() { n=g(),m=g(),tr=g(),mod=g(); for(R i=1;i<=n;++i) w[i]=g(); for(R i=1,u,v;i<n;++i) u=g(),v=g(),add(u,v),add(v,u); cnt=0; d[tr]=1; dfs(tr),dfs_(tr,tr); build(1,1,n); //for(R i=1;i<=n;++i) cout<<sz[i]<<d[i]<<dfn[i]<<pre[i]<<son[i]<<top[i]<<endl; for(R i=1;i<=m;++i) { R k=g(),u=g(),v,inc; //cout<<k<<u<<endl; if(k==1) v=g(),inc=g(),change(u,v,inc%mod); else if(k==2) v=g(),printf("%lld ",qTree(u,v)); else if(k==3) v=g(),update(1,1,n,dfn[u],dfn[u]+sz[u]-1,v%mod); else printf("%lld ",query(1,1,n,dfn[u],dfn[u]+sz[u]-1)); } }
2019.04.19