#include<stdio.h>
#include<string.h>
#include<string>
#include<math.h>
#include<algorithm>
#include<iostream>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<stdlib.h>
#include<time.h>
#include <iomanip>
#define lowbit(x) (x&(-x))
#define inf 0x7fffffff
#define linf 0x7fffffffffffffff
#define mem(x,y) memset(x,y,sizeof(x))
#define fup(i,x,y) for(int i=(x);i<=(y);i++)
#define fdn(i,x,y) for(int i=(x);i>=(y);i--)
#define sp(x) setprecision(x)
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define sld(n) scanf("%lld",&n)
#define sldd(n,m) scanf("%lld%lld",&n,&m)
#define slddd(n,m,k) scanf("%lld%lld%lld",&n,&m,&k)
#define sf(n) scanf("%lf",&n)
#define sff(n,m) scanf("%lf%lf",&n,&m)
#define sfff(n,m,k) scanf("%lf%lf%lf",&n,&m,&k)
#define sc(n) scanf("%s",&n)
#define pf(x) printf("%d\n",x)
#define pfl(x) printf("%lld\n",x)
#define pff(x) printf("%lf\n",x)
#define N 100005
#define M 4000009
#define pi acos(-1)
#define eps 1e-2
//cout.setf(ios::fixed);
//freopen("out.txt","w",stdout);
using namespace std;
typedef long long ll;
typedef double db;
const ll mod=1e9+7;
struct node
{
int go;
node(int x):go(x){}
};
int f[N],d[N],siz[N],son[N],rk[N],top[N],id[N],a[N],n;
vector<node> edg[N];
int t[3*N],add[3*N],p;
void down(int r,int st,int ed)
{
if(add[r])
{
add[r<<1]+=add[r];
add[r<<1]%=p;
add[r<<1|1]+=add[r];
add[r<<1|1]%=p;
int mid=(st+ed)>>1;
t[r<<1]+=add[r]*(mid-st+1);
t[r<<1|1]+=add[r]*(ed-mid);
t[r<<1]%=p;
t[r<<1|1]%=p;
add[r]=0;
}
}
void build(int r,int st,int ed)
{
if(st==ed) t[r]=a[rk[st]];
else
{
int mid=(st+ed)>>1;
build(r<<1,st,mid);
build(r<<1|1,mid+1,ed);
t[r]=t[r<<1]+t[r<<1|1];
t[r]%=p;
}
}
void update(int r,int st,int ed,int x,int y,int z)
{
if(st>y||ed<x) return ;
if(st>=x&&ed<=y)
{
add[r]+=z;
add[r]%=p;
t[r]+=z*(ed-st+1);
t[r]%=p;
return ;
}
down(r,st,ed);
int mid=(st+ed)>>1;
update(r<<1|1,mid+1,ed,x,y,z);
update(r<<1,st,mid,x,y,z);
t[r]=t[r<<1]+t[r<<1|1];
t[r]%=p;
}
int findm(int r,int st,int ed,int x,int y)
{
if(st>y||ed<x) return 0;
if(st>=x&&ed<=y) return t[r];
down(r,st,ed);
int mid=(st+ed)>>1;
return (findm(r<<1,st,mid,x,y)%p+findm(r<<1|1,mid+1,ed,x,y)%p)%p;
}
void dfs1(int x,int fa,int dep)
{
f[x]=fa;
siz[x]=1;
d[x]=dep;
for(int i=0;i<edg[x].size();i++)
{
node tp=edg[x][i];
if(tp.go!=fa)
{
dfs1(tp.go,x,dep+1);
siz[x]+=siz[tp.go];
if(siz[tp.go]>siz[son[x]]) son[x]=tp.go;
}
}
}
int cnt;
void dfs2(int x,int t)
{
top[x]=t;
id[x]=++cnt;
rk[cnt]=x;
if(!son[x]) return ;
dfs2(son[x],t);
for(int i=0;i<edg[x].size();i++)
{
node tp=edg[x][i];
if(tp.go!=son[x]&&tp.go!=f[x]) dfs2(tp.go,tp.go);
}
}
int sum(int x,int y)
{
int ans=0,fx=top[x],fy=top[y];
while(fx!=fy)
{
if(d[fx]>d[fy])
{
ans+=findm(1,1,n,id[fx],id[x]);
x=f[fx];
ans%=p;
}
else
{
ans+=findm(1,1,n,id[fy],id[y]);
y=f[fy];
ans%=p;
}
fx=top[x];
fy=top[y];
}
if(id[x]<=id[y]) ans+=findm(1,1,n,id[x],id[y]);
else ans+=findm(1,1,n,id[y],id[x]);
return ans%p;
}
void updateson(int x,int y,int c)
{
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(d[fx]>=d[fy])
{
update(1,1,n,id[fx],id[x],c);
x=f[fx];
}
else
{
update(1,1,n,id[fy],id[y],c);
y=f[fy];
}
fx=top[x];
fy=top[y];
}
if(id[x]<=id[y]) update(1,1,n,id[x],id[y],c);
else update(1,1,n,id[y],id[x],c);
}
int main()
{
int m,r;
sddd(n,m,r);
sd(p);
fup(i,1,n)
sd(a[i]),a[i]%=p;
fup(i,1,n-1)
{
int x,y;
sdd(x,y);
edg[x].push_back(node(y));
edg[y].push_back(node(x));
}
dfs1(r,0,1);
dfs2(r,r);
build(1,1,n);
while(m--)
{
int op,x,y,z;
sd(op);
if(op==1)
{
sddd(x,y,z);
updateson(x,y,z%p);
}
else if(op==2)
{
sdd(x,y);
pf(sum(x,y)%p);
}
else if(op==3)
{
sdd(x,z);
update(1,1,n,id[x],id[x]+siz[x]-1,z%p);
}
else if(op==4)
{
sd(x);
pf(findm(1,1,n,id[x],id[x]+siz[x]-1)%p);
}
}
return 0;
}
/*
66928 66992
67095 71145
*/
落谷P3384树链剖分
最新推荐文章于 2023-05-15 21:36:49 发布