like_tis @ 2023-11-25 20:28:57
#include<bits/stdc++.h>
#define ll long long
#define N 100005
using namespace std;
int n,T,r,p,vis;
int dep[N],Size[N],wc[N],fa[N],top[N],rdfn[N],dfn[N];
vector<int> tree[N];
ll a[N];
//dfn:树编号-->链编号
//rdfn:链编号-->树编号
namespace seg{
ll w[N*4]={0},tag[N*4]={0};
void pushup(int u){
w[u]=(w[u*2]+w[u*2+1])%p;
}
void maketag(int u,int len,ll v){
tag[u]+=v;
w[u]+=len*v%p;
tag[u]%=p;
w[u]%=p;
}
void pushdown(int u,int l,int r){
int mid=(l+r)/2;
maketag(u*2,mid-l+1,tag[u]);
maketag(u*2+1,r-mid,tag[u]);
tag[u]=0;
}
bool inRange(int l,int r,int L,int R){
return(L<=l&&r<=R);
}
bool outOfRange(int l,int r,int L,int R){
return(l>R||r<L);
}
void build(int u,int l,int r){
if(l==r){
w[u]=a[rdfn[u]]%p;
return;
}
int mid=(l+r)/2;
build(u*2,l,mid);
build(u*2+1,mid+1,r);
pushup(u);
}
ll query(int u,int l,int r,int L,int R){
if(inRange(l,r,L,R)) return w[u]%p;
else if(!outOfRange(l,r,L,R)){
int mid=(l+r)/2;
pushdown(u,l,r);
return (query(u*2,l,mid,L,R)+query(u*2+1,mid+1,r,L,R))%p;
}
else return 0;
}
void update(int u,int l,int r,int L,int R,ll v){
if(inRange(l,r,L,R)) maketag(u,r-l+1,v);
else if(!outOfRange(l,r,L,R)){
int mid=(l+r)/2;
pushdown(u,l,r);
update(u*2,l,mid,L,R,v);
update(u*2+1,mid+1,r,L,R,v);
pushup(u);
}
}
}
void dfs1(int u,int from){
dep[u]=dep[from]+1;
Size[u]=1;
fa[u]=from;
for(auto v:tree[u])if(v!=from){
dfs1(v,u);
Size[u]+=Size[v];
if(Size[v]>Size[wc[u]]) wc[u]=v;
}
}
void dfs2(int u,int Top){
dfn[u]=++vis;
rdfn[vis]=u;
top[u]=Top;
if(wc[u]!=0){
dfs2(wc[u],Top);
for(auto v:tree[u])if(v!=fa[u]&&v!=wc[u]){
dfs2(v,v);
}
}
}
ll qry(int x,int y){
ll ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans+=seg::query(1,1,n,dfn[top[x]],dfn[x]);
ans%=p;
x=fa[top[x]];
}
ans+=seg::query(1,1,n,min(dfn[x],dfn[y]),max(dfn[x],dfn[y]));
ans%=p;
return ans;
}
void upd(int x,int y,ll v){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
seg::update(1,1,n,dfn[top[x]],dfn[x],v);
x=fa[top[x]];
}
seg::update(1,1,n,min(dfn[x],dfn[y]),max(dfn[x],dfn[y]),v);
}
int main(){
scanf("%d%d%d%d",&n,&T,&r,&p);
for(int i=1;i<=n;i++) scanf("%lld",a+i);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
tree[u].push_back(v);
tree[v].push_back(u);
}
dfs1(r,0);
dfs2(r,0);
seg::build(1,1,n);
while(T--){
int op,x,y,z;
scanf("%d",&op);
if(op==1){
scanf("%d%d%d",&x,&y,&z);
upd(x,y,z);
}
else if(op==2){
scanf("%d%d",&x,&y);
printf("%lld\n",qry(x,y));
}
else if(op==3){
scanf("%d%d",&x,&z);
seg::update(1,1,n,dfn[x],dfn[x]+Size[x]-1,z);
}
else{
scanf("%d",&x);
printf("%lld\n",seg::query(1,1,n,dfn[x],dfn[x]+Size[x]-1));
}
}
return 0;
}
by like_tis @ 2023-11-25 20:35:07
发现了一个dfs2(r,0);
应该写成dfs2(r,r);
但还是错的
by lixiaze1234567 @ 2023-11-25 20:36:07
能过的了我把你吃了
by like_tis @ 2023-11-25 20:39:56
@lixiaze1234567
你什么意思
by lixiaze1234567 @ 2023-11-26 10:31:33
我没看到你上一条发的
by like_tis @ 2023-11-26 12:09:48
此贴结
build
中的w[u]=a[rdfn[u]]%p;
应写为w[u]=a[rdfn[l]]%p;
警示后人
by Jorisy @ 2024-04-14 16:14:10
@like_tis_yzx 谢谢你,我也是错的这个 /tuu