xyztapeplayer @ 2024-04-26 17:18:37
#include<bits/stdc++.h>
using namespace std;
struct node{
int l,r,sum,lz;
};
node tree[400005];
vector<int> a[400005];
int in[400005],deep[400005],siz[400005],fa[400005],son[400005],rnk[400005],top[400005],dfn[400005],cnt,n,m,mod,root;
void build(long long p,long long l,long long r){
tree[p].l=l,tree[p].r=r;
if(l==r){tree[p].sum=rnk[l];return;}
long long mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
tree[p].sum=(tree[p*2].sum+tree[p*2+1].sum)%mod;
}
void push_down(int p){
if(!tree[p].lz) return;
tree[p*2].lz+=tree[p].lz;
tree[p*2+1].lz+=tree[p].lz;
int mid=(tree[p].l+tree[p].r)/2;
tree[p*2].sum+=tree[p].lz*(mid-tree[p*2].l+1);
tree[p*2+1].sum+=tree[p].lz*(tree[p*2+1].r-mid);
tree[p].lz=0;
}
void add(int p,int l,int r,int k){
// cout<<p<<" "<<l<<" "<<r<<endl;
if(tree[p].l>=l&&tree[p].r<=r){
tree[p].sum+=k*(tree[p].r-tree[p].l+1);
tree[p].lz+=k;
return;
}
push_down(p);
int mid=(tree[p].l+tree[p].r)/2;
if(mid>=l) add(p*2,l,r,k);
if(mid<r) add(p*2+1,l,r,k);
tree[p].sum=(tree[p*2].sum+tree[p*2+1].sum)%mod;
//cout<<tree[p].l<<" "<<tree[p].r<<" "<<tree[p].sum<<endl;
}
int search(int p,int l,int r){
if(tree[p].l>=l&&tree[p].r<=r){
return tree[p].sum;
}
if(tree[p].r<l||tree[p].l>r) return 0;
push_down(p);
int s=0;
int mid=(tree[p].l+tree[p].r)/2;
if(mid>=l) s+=search(p*2,l,r);
s%=mod;
if(mid<r) s+=search(p*2+1,l,r);
s%=mod;
//cout<<tree[p].l<<" "<<tree[p].r<<" "<<s<<endl;
return s;
}
void dfs1(int u,int f){
siz[u]=1;
// cout<<u<<endl;
for(int i=0;i<a[u].size();i++){
if(a[u][i]==f) continue;
// cout<<i<<":"<<a[u][i]<<endl;
fa[a[u][i]]=u;
deep[a[u][i]]=deep[u]+1;
dfs1(a[u][i],u);
siz[u]+=siz[a[u][i]];
if(siz[a[u][i]]>siz[son[u]]) son[u]=a[u][i];
}
}
void dfs2(int u,int tp){
dfn[u]=++cnt;
top[u]=tp;
rnk[cnt]=in[u];
if(!son[u]) return;
dfs2(son[u],tp);
for(int i=0;i<a[u].size();i++){
if(a[u][i]!=fa[u]&&a[u][i]!=son[u])
dfs2(a[u][i],a[u][i]);
}
}
void addtree(int x,int y,int c){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
add(1,dfn[top[x]],dfn[x],c);
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
add(1,dfn[x],dfn[y],c);
}
int searchtree(int x,int y){
int ans=0;
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]]) swap(x,y);
ans+=search(1,dfn[top[x]],dfn[x]);
ans%=mod;
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
ans+=search(1,dfn[x],dfn[y]);
ans%=mod;
return ans;
}
int main(){
cin>>n>>m>>root>>mod;
for(int i=1;i<=n;i++) cin>>in[i];
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
}
// cout<<"图:"<<endl;
// for(int i=1;i<=n;i++){
// cout<<i<<": ";
// for(int j=0;j<a[i].size();j++) cout<<a[i][j]<<" ";
// cout<<endl;
// }
// cout<<"dfs1:"<<endl;
fa[root]=root;
dfs1(root,root);
dfs2(root,root);
// build(1,1,n);
// cout<<"dfs序: ";
// for(int i=1;i<=n;i++) cout<<dfn[i]<<" ";
// cout<<endl<<"子树大小: ";
// for(int i=1;i<=n;i++) cout<<siz[i]<<" ";
// cout<<endl<<"重儿子: ";
// for(int i=1;i<=n;i++) cout<<son[i]<<" ";
// cout<<endl<<"深度: ";
// for(int i=1;i<=n;i++) cout<<deep[i]<<" ";
// cout<<endl<<"父亲: ";
// for(int i=1;i<=n;i++) cout<<fa[i]<<" ";
// cout<<endl<<"当前DFS序对应的值: ";
// for(int i=1;i<=n;i++) cout<<rnk[i]<<" ";
// cout<<endl;
while(m--){
int op;
cin>>op;
if(op==1){
int x,y,z;
cin>>x>>y>>z;
addtree(x,y,z);
}
if(op==2){
int x,y;
cin>>x>>y;
cout<<searchtree(x,y)<<endl;
}
if(op==3){
int x,y;
cin>>x>>y;
add(1,dfn[x],dfn[x]+siz[x]-1,y%mod);
}
if(op==4){
int x;
cin>>x;
cout<<search(1,dfn[x],dfn[x]+siz[x]-1)<<endl;
}
}
return 0;
}
by xyztapeplayer @ 2024-04-26 17:19:03
提交记录