mzycの喰种 @ 2023-07-12 20:50:27
#include<bits/stdc++.h>
using namespace std;
#define N 2*114514
#define M 1919810
#define ll long long
#define ls now<<1
#define rs now<<1|1
#define INF 1145141919810
ll n,a,b,c,w[N],q,root,mod;
ll opt;
struct xx{
ll next,to,val;
}e[2*N];
ll head[2*N],cnt;
void add(ll x,ll y){
e[++cnt].next=head[x];
e[cnt].to=y;
head[x]=cnt;
}
struct tree{
ll l,r;
ll sum,add;
ll len;
}t[4*N];
ll f[N],dept[N],size[N],son[N];
//父节点/深度/字数大小/重儿子
void dfs1(ll u,ll dep){ //处理出每个点的信息
size[u]=1;
dept[u]=dep;
for(int i=head[u];i;i=e[i].next){
ll v=e[i].to;
if(v==f[u]) continue;
f[v]=u;
dfs1(v,dep+1);
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
}
ll top[N],dfn[N],rk[N],t_cnt; //记录重链,dfs序,重链节点对应点编号
void dfs2(ll u,ll t){ //t为重链顶端
top[u]=t;
dfn[u]=++t_cnt;
rk[t_cnt]=u;
if(!son[u]) return;
dfs2(son[u],t);
for(int i=head[u];i;i=e[i].next){
ll v=e[i].to;
if(v!=son[u]&&v!=f[u]) dfs2(v,v); //位于轻链底端则top为他本身
}
}
void pushup(ll now){
t[now].sum=t[ls].sum+t[rs].sum;
t[now].sum%=mod;
}
void pushdown(ll now){
t[ls].add+=t[now].add;
t[ls].sum+=t[now].add*t[now].len;
t[rs].add+=t[now].add;
t[rs].sum+=t[now].add*t[now].len;
t[now].add=0;
}
void build(ll now,ll l,ll r){
t[now].l=l,t[now].r=r;
t[now].len=r-l+1,t[now].add=0;
if(l==r){
t[now].sum=w[rk[l]];
return;
}
ll mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(now);
}
void update(ll now,ll x,ll y,ll k){
if(t[now].l>=x&&t[now].r<=y){
t[now].add+=k;
t[now].sum+=t[now].len*k;
t[now].sum%=mod;
return;
}
pushdown(now);
ll mid=t[now].l+t[now].r>>1;
if(x<=mid) update(ls,x,y,k);
if(y>mid) update(rs,x,y,k);
pushup(now);
}
void update_side(ll u,ll v,ll k){
k%=mod;
while(top[u]!=top[v]){
if(dept[top[u]]<=dept[top[v]]) swap(u,v);
update(1,dfn[top[u]],dfn[u],k);
u=f[top[u]];
}
if(dept[u]<dept[v]) swap(u,v);
update(1,dfn[u],dfn[v],k);
}
void update_son(ll x,ll k){
update(1,dfn[x],dfn[x]+size[x]-1,k);
}
ll qsum(ll now,ll x,ll y){
if(t[now].l>=x&&t[now].r<=y) return t[now].sum;
ll mid=t[now].l+t[now].r>>1,ans=0;
pushdown(now);
if(x<=mid) ans+=qsum(ls,x,y),ans%=mod;
if(y>mid) ans+=qsum(rs,x,y),ans%=mod;
pushup(now);
return ans;
}
ll QSUM(ll u,ll v){
ll ans=0;
while(top[u]!=top[v]){ //LCA
if(dept[top[u]]<dept[top[v]]) swap(u,v);
ans+=qsum(1,dfn[top[u]],dfn[u]);
ans%=mod;
u=f[top[u]];
}
if(dept[u]<dept[v]) swap(u,v);
ans+=qsum(1,dfn[v],dfn[u]);
return ans;
}
ll QSON(ll x){
return qsum(1,dfn[x],dfn[x]+size[x]-1)%mod; //注意
}
int main(){
//ios::sync_with_stdio(0);
//cin.tie(0); cout.tie(0);
cin>>n>>q>>root>>mod;
for(int i=1;i<=n;++i) cin>>w[i];
for(int i=1;i<n;++i){
cin>>a>>b;
add(a,b);
add(b,a);
}
dfs1(root,0); dfs2(root,root);
build(1,1,n);
//for(int i=1;i<=4*n;++i) cout<<t[i].len<<" "; cout<<'\n';
while(q--){
cin>>opt;
if(opt==1) cin>>a>>b>>c,update_side(a,b,c);
if(opt==2) cin>>a>>b,cout<<QSUM(a,b)%mod<<'\n';
if(opt==3) cin>>a>>b,update_son(a,b);
if(opt==4) cin>>a,cout<<QSON(a)%mod<<'\n';
//for(int i=1;i<=4*n;++i) cout<<t[i].sum<<'\n';
}
return 0;
}
/*
5 5 2 24
7 3 7 8 0
1 2
1 5
3 1
4 1
3 4 2
3 2 2
4 5
1 5 1 3
2 1 3
*/
样例都过不了,对拍也只拍了个寂寞
by mzycの喰种 @ 2023-07-12 20:56:24
救救萌新
by Zzzcr @ 2023-07-12 21:03:09
pushdown写错了,还有query不需要pushup
void pushdown(ll now)
{
t[ls].add += t[now].add;
t[ls].sum += t[now].add * t[ls].len;
t[rs].add += t[now].add;
t[rs].sum += t[now].add * t[rs].len;
t[now].add = 0;
}
by mzycの喰种 @ 2023-07-12 21:05:28
@Zzzcr 哦哦,谢谢大佬,还有pushup应该多加了没影响吧
by mzycの喰种 @ 2023-07-12 21:08:12
az,还是WA 28pts
by mzycの喰种 @ 2023-07-12 21:14:50
已过,update_side里面一个大于写成了小于,警钟长鸣……