青莲武者 @ 2024-08-16 13:55:17
#include<bits/stdc++.h>
using namespace std;
int n,m,r,P;
int p[200005],siz[200005],d[200005],son[200005],top[200005],id[200005],cnt,val[200005],f[200005];
vector<int> c[200005],tr[200005];
int L[800005],R[800005];
long long sum[800005],lazy[800005];
void build(int l, int r, int x){
L[x] = l, R[x] = r, lazy[x] = 0;
if (l == r) {
sum[x]=val[l]%P;
return;
}
int mid = (l + r) / 2;
build(l, mid, x * 2);
build(mid + 1, r, x * 2 + 1);
sum[x] = (sum[x*2]+sum[x*2+1])%P;
return;
}
int Len(int x){
return R[x] - L[x] + 1;
}
void pushdown(int x){
if (lazy[x]){
lazy[x * 2]=(lazy[x*2]+lazy[x])%P;
lazy[x * 2 + 1]=(lazy[x*2+1]+lazy[x])%P;
sum[x * 2]=(sum[x*2]+lazy[x] * Len(x * 2))%P;
sum[x * 2 + 1]=(sum[x*2+1]+lazy[x] * Len(x * 2+1))%P;
lazy[x] = 0;
}
return;
}
void update(int l, int r, int x, long long k){
if (l <= L[x] && R[x] <= r){
lazy[x]=(lazy[x]+k)%P;
sum[x]=(sum[x]+k *Len(x))%P;
return;
}
pushdown(x);
int mid = (L[x] + R[x]) / 2;
if (l <= mid) update(l, r, x * 2, k);
if (r > mid) update(l, r, x * 2 + 1, k);
sum[x] =(sum[x * 2] + sum[x * 2 + 1])%P;
}
long long query(int l, int r, int x){
if (l <= L[x] && R[x] <= r){
return sum[x];
}
pushdown(x);
long long ret = 0; int mid = (L[x] + R[x]) / 2;
if (l <= mid) ret += query(l, r, x * 2);
if (r > mid) ret += query(l, r, x * 2 + 1);
return ret%P;
}
void dfs1(int nowp,int dep){
siz[nowp]=1;
d[nowp]=dep;
for(int i=0;i<c[nowp].size();++i){
if(c[nowp][i]!=f[nowp]){
f[c[nowp][i]]=nowp;
dfs1(c[nowp][i],dep+1);
tr[nowp].push_back(c[nowp][i]);
siz[nowp]+=siz[c[nowp][i]];
if(siz[c[nowp][i]]>siz[son[nowp]]){
son[nowp]=c[nowp][i];
}
}
}
if(siz[nowp]==1) son[nowp]=-1;
}
void dfs2(int nowp,int topx){
id[nowp]=++cnt;
val[cnt]=p[nowp];
top[cnt]=topx;
if(son[nowp]==-1) return;
dfs2(son[nowp],topx);
for(int i=0;i<tr[nowp].size();++i){
if(tr[nowp][i]!=son[nowp]){
dfs2(tr[nowp][i],tr[nowp][i]);
}
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>r>>P;
for(int i=1;i<=n;++i) cin>>p[i];
for(int i=1;i<n;++i){
int a,b;
cin>>a>>b;
c[a].push_back(b);
c[b].push_back(a);
}
f[r]=0;
dfs1(r,0);
dfs2(r,r);
build(1,n,1);
while(m--){
int op,x,y,z;
cin>>op;
if(op==1){
cin>>x>>y>>z;
while(top[id[x]]!=top[id[y]]){
if(d[top[id[x]]]<d[top[id[y]]]) swap(x,y);
update(id[top[id[x]]],id[x],1,z%P);
x=f[top[x]];
}
if(d[x]>d[y]) swap(x,y);
update(id[x],id[y],1,z%P);
}else if(op==2){
cin>>x>>y;
long long ret=0;
while(top[id[x]]!=top[id[y]]){
if(d[top[id[x]]]<d[top[id[y]]]) swap(x,y);
ret+=query(id[top[id[x]]],id[x],1);
x=f[top[id[x]]];
}
if(d[x]>d[y]) swap(x,y);
ret+=query(id[x],id[y],1);
cout<<ret%P<<'\n';
}else if(op==3){
cin>>x>>z;
update(id[x],id[x]+siz[id[x]]-1,1,z%P);
}else{
cin>>x;
cout<<query(id[x],id[x]+siz[id[x]]-1,1)%P<<'\n';
}
}
return 0;
}
by __cheng827922__ @ 2024-08-16 14:22:38
@liwanxian 但是他怎么有管理员标签?
by clzzw666 @ 2024-08-16 14:28:16
@青莲武者 你有op==1
的时候x=f[top[x]];
应为x=f[top[id[x]]];
,不会TLE了,但会WA。。。
by liwanxian @ 2024-08-16 14:28:32
@cheng827922 不知道,但是ta个人主页不能查看,用户类型是普通用户
by clzzw666 @ 2024-08-16 14:29:28
@cheng827922 管理员不管理后可要一个。。。
by 青莲武者 @ 2024-08-16 14:31:42
@clzzw666 这个我也测出来了,按照您的数据是这样的。
264
1211
2502
1789
by clzzw666 @ 2024-08-16 14:32:37
那就是题目中的数据。。。
输出是
1208
1055
2346
1900
by 青莲武者 @ 2024-08-16 14:33:53
谢谢您几位,调出来了。问题是opt=3和4时siz数组里不应当用id[x]。
by clzzw666 @ 2024-08-16 14:36:04
。。。去理解dfs1和dfs2去了,没看后面。。。
by clzzw666 @ 2024-08-16 14:37:12
顺便带几道模板题
P2590 P3178 P3833
by __cheng827922__ @ 2024-08-16 14:52:47
@liwanxian 是ta之前是管理员 等等 似乎有可能是ta橙掉蓝了