Purple_meteor @ 2024-05-27 16:39:53
#include<bits/stdc++.h>
using namespace std;
const int N=1e7+1;
int n,m,r,mod,num;
int w[N];
struct point
{
int id,w,head,son,f,total,depth,topp;
}p[N];
struct line
{
int f,t,next;
}l[N];
int tot;
void fun(int f,int t)
{
l[++tot].f=f;
l[tot].t=t;
l[tot].next=p[f].head;
p[f].head=tot;
}
void dfs1(int x,int depth)
{
p[x].total=1;
p[x].depth=depth;
int maxn=-1;
for(int i=p[x].head;i;i=l[i].next)
{
if(l[i].t==p[x].f) continue;
p[l[i].t].f=x;
dfs1(l[i].t,depth+1);
p[x].total+=p[l[i].t].total;
if(p[l[i].t].total>maxn)
{
maxn=p[l[i].t].total;
p[x].son=l[i].t;
}
}
}
void dfs2(int x,int topp)
{
p[x].id=++num;
w[num]=p[x].w;
p[x].topp=topp;
if(!p[x].son) return ;
dfs2(p[x].son,topp);
for(int i=p[x].head;i;i=l[i].next)
{
if(l[i].t==p[x].f||l[i].t==p[x].son) continue;
dfs2(l[i].t,l[i].t);
}
}
struct tree
{
int w,tag;
}t[N];
int ls(int x)
{
return x<<1;
}
int rs(int x)
{
return x<<1|1;
}
void push_up(int rt)
{
t[rt].w=(t[rt*2].w+t[rt*2+1].w)%mod;
}
void push_down(int rt,int l,int r)
{
t[ls(rt)].tag+=t[rt].tag;
t[rs(rt)].tag+=t[rt].tag;
t[ls(rt)].w+=((r+l)/2-l+1)*t[rt].tag;
t[ls(rt)].w%=mod;
t[rs(rt)].w+=(r-(r+l)/2)*t[rt].tag;
t[rs(rt)].w%=mod;
t[rt].tag=0;
}
void build(int rt,int l,int r)
{
if(l==r)
{
t[rt].w=w[l]%mod;
return ;
}
int mid=(l+r)/2;
build(ls(rt),l,mid);
build(rs(rt),mid+1,r);
push_up(rt);
}
void update(int rt,int l,int r,int ql,int qr,int k)
{
if(ql<=l&&qr>=r)
{
t[rt].tag+=k;
t[rt].w+=k*(r-l+1);
t[rt].w%=mod;
return ;
}
if(t[rt].tag) push_down(rt,l,r);
int mid=(r+l)/2;
if(ql<=mid) update(ls(rt),l,mid,ql,qr,k);
if(qr>mid) update(rs(rt),mid+1,r,ql,qr,k);
push_up(rt);
return ;
}
int query(int rt,int l,int r,int ql,int qr)
{
if(ql<=l&&qr>=r) return t[rt].w;
if(t[rt].tag) push_down(rt,l,r);
int mid=(r+l)/2,ans=0;
if(ql<=mid) ans+=query(ls(rt),l,mid,ql,qr),ans%=mod;
if(qr>mid) ans+=query(rs(rt),mid+1,r,ql,qr),ans%=mod;
push_up(rt);
return ans;
}
int qrange(int x,int y)
{
int ans=0;
while(p[x].topp!=p[y].topp)
{
if(p[p[x].topp].depth<p[p[y].topp].depth) swap(x,y);
ans+=query(1,1,n,p[p[x].topp].id,p[x].id);
ans%=mod;
x=p[p[x].topp].f;
}
if(p[x].depth>p[y].depth) swap(x,y);
ans+=query(1,1,n,p[x].id,p[y].id);
return ans%mod;
}
void uprange(int x,int y,int z)
{
while(p[x].topp!=p[y].topp)
{
if(p[p[x].topp].depth<p[p[y].topp].depth) swap(x,y);
update(1,1,n,p[p[x].topp].id,p[x].id,z);
x=p[p[x].topp].f;
}
if(p[x].depth>p[y].depth) swap(x,y);
update(1,1,n,p[x].id,p[y].id,z);
}
int qson(int x)
{
return query(1,1,n,p[x].id,p[x].id+p[x].total-1);
}
int upson(int x,int y)
{
update(1,1,n,p[x].id,p[x].id+p[x].total-1,y);
}
int main()
{
//freopen(".in","r",stdin);
cin>>n>>m>>r>>mod;
for(int i=1;i<=n;i++)
cin>>p[i].w;
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
fun(x,y);
fun(y,x);
}
dfs1(r,1);
dfs2(r,r);
build(1,1,n);
for(int i=1;i<=m;i++)
{
int op,x,y,z;
cin>>op;
switch(op)
{
case 1:
{
cin>>x>>y>>z;
uprange(x,y,z);
break;
}
case 2:
{
cin>>x>>y;
cout<<qrange(x,y)<<endl;
break;
}
case 3:
{
cin>>x>>z;
upson(x,z);
break;
}
case 4:
{
cin>>x;
cout<<qson(x)<<endl;
break;
}
}
}
return 0;
}
by hytallenxu @ 2024-05-27 17:01:37
upson没有返回值 @Purple_meteor
by Purple_meteor @ 2024-05-31 15:56:45
@hytallenxu 非常感谢!成功AC,已关,此贴结
by 090810mzh @ 2024-08-07 16:22:29
@hytallenxu 感谢大佬!orz