.
.
.
.
.
分析
树剖+线段树
(我的代码太丑了,打了170+行)
.
.
.
.
.
程序:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
struct edge
{
int to,from;
}e[500010];
int head[500010],n,size[500010],dep[500010],fa[500010],id[500010],a[500010];
int rk[500010],top[500010],son[500010],cnt=0,tot=0,sum[500010],p,lazy[500010];
void add(int x,int y)
{
e[++cnt].to=y;e[cnt].from=head[x];head[x]=cnt;
e[++cnt].to=x;e[cnt].from=head[y];head[y]=cnt;
}
void dfs1(int x,int father)
{
fa[x]=father;
dep[x]=dep[father]+1;
size[x]=1;
for (int i=head[x];i;i=e[i].from)
if (e[i].to!=father)
{
dfs1(e[i].to,x);
size[x]+=size[e[i].to];
if (size[e[i].to]>size[son[x]]) son[x]=e[i].to;
}
}
void dfs2(int x,int father)
{
id[x]=++tot;
rk[tot]=x;
top[x]=father;
if (son[x]) dfs2(son[x],father);
for (int i=head[x];i;i=e[i].from)
if (e[i].to!=son[x]&&e[i].to!=fa[x]) dfs2(e[i].to,e[i].to);
}
void build(int l,int r,int d)
{
if (l==r)
{
sum[d]=a[rk[l]]%p;
return;
}
int mid=(l+r)/2;
build(l,mid,d*2);
build(mid+1,r,d*2+1);
sum[d]=(sum[d*2]+sum[d*2+1])%p;
}
void pushdown(int l,int r,int d)
{
int mid=(l+r)/2;
lazy[d*2]=(lazy[d*2]+lazy[d])%p;
lazy[d*2+1]=(lazy[d*2+1]+lazy[d])%p;
sum[d*2]=(sum[d*2]+lazy[d]*(mid-l+1))%p;
sum[d*2+1]=(sum[d*2+1]+lazy[d]*(r-mid))%p;
lazy[d]=0;
}
void update(int l,int r,int d,int x,int y,int z)
{
if (x<=l&&y>=r)
{
sum[d]=(sum[d]+z*(r-l+1))%p;
lazy[d]=(lazy[d]+z)%p;
return;
}
if (l>y||r<x) return;
int mid=(l+r)/2;
if (lazy[d]!=0) pushdown(l,r,d);
if (mid>=x) update(l,mid,d*2,x,y,z);
if (mid<y) update(mid+1,r,d*2+1,x,y,z);
sum[d]=(sum[d*2]+sum[d*2+1])%p;
}
int querysum(int l,int r,int d,int x,int y)
{
int ans=0,mid=(l+r)/2;
if (x<=l&&r<=y) return sum[d]%p;
if (l>y||r<x) return 0;
if (lazy[d]) pushdown(l,r,d);
if (x<=mid) ans=(ans+querysum(l,mid,d*2,x,y))%p;
if (y>mid) ans=(ans+querysum(mid+1,r,d*2+1,x,y))%p;
sum[d]=(sum[d*2]+sum[d*2+1])%p;
return ans%p;
}
int getsum(int x,int y)
{
int ans=0,fx=top[x],fy=top[y];
while (fx!=fy)
{
if (dep[fx]<dep[fy])
{
swap(x,y);
swap(fx,fy);
}
ans=(ans+querysum(1,tot,1,id[fx],id[x]))%p;
x=fa[fx];
fx=top[x];
}
if (id[x]>id[y]) swap(x,y);
ans=(ans+querysum(1,tot,1,id[x],id[y]))%p;
return ans%p;
}
void work1(int x,int y,int z)
{
int fx=top[x],fy=top[y];
while (fx!=fy)
{
if (dep[fx]<dep[fy])
{
swap(x,y);
swap(fx,fy);
}
update(1,tot,1,id[fx],id[x],z);
x=fa[fx];
fx=top[x];
}
if (id[x]>id[y]) swap(x,y);
update(1,tot,1,id[x],id[y],z);
}
int main()
{
int m,r;
scanf("%d%d%d%d",&n,&m,&r,&p);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
for (int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
dfs1(r,0);
fa[r]=1;
dep[r]=1;
dfs2(r,r);
build(1,n,1);
while (m--)
{
int k,x,y,z;
scanf("%d",&k);
if (k==1)
{
scanf("%d%d%d",&x,&y,&z);
work1(x,y,z%p);
}
if (k==2)
{
scanf("%d%d",&x,&y);
printf("%d\n",getsum(x,y));
}
if (k==3)
{
scanf("%d%d",&x,&y);
update(1,n,1,id[x],id[x]+size[x]-1,y%p);
}
if (k==4)
{
scanf("%d",&x);
printf("%d\n",querysum(1,n,1,id[x],id[x]+size[x]-1));
}
}
return 0;
}