rt,只有20分,其他点都RE了
代码:
#include<bits/stdc++.h>
#define ll long long
#define ls(k) k<<1
#define rs(k) (k<<1)+1
#define N 500010
using namespace std;
int n,m,r,mod,head[N],op,x,y,z,cnt,tot,pos[N],w[N],dis[N],son[N],ti[N],f[N],size[N],top[N];
struct edge{
int to,next;
}e[N*2];
struct SegmentTree{
int add,l,r;
ll sum;
}tree[N*4];
ll read(){
ll x=0;
char ch=getchar();
while(ch<'0'||ch>'9'){
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
return x;
}
void add(int u,int v){
e[++cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
}
void Pushup(int x){
tree[x].sum=(tree[ls(x)].sum+tree[rs(x)].sum)%mod;
}
void Pushdown(int x){
tree[ls(x)].sum=(tree[ls(x)].sum+(tree[ls(x)].r-tree[ls(x)].l+1)*tree[x].add)%mod;
tree[rs(x)].sum=(tree[rs(x)].sum+(tree[rs(x)].r-tree[rs(x)].l+1)*tree[x].add)%mod;
tree[ls(x)].add=(tree[ls(x)].add+tree[x].add)%mod;
tree[rs(x)].add=(tree[rs(x)].add+tree[x].add)%mod;
tree[x].add=0;
}
void Build(int k,int l,int r){
tree[k].l=l,tree[k].r=r;
if(tree[k].l==tree[k].r){
tree[k].sum=pos[l];
return;
}
int mid=(l+r)/2;
Build(ls(k),l,mid),Build(rs(k),mid+1,r);
Pushup(k);
}
void dfs1(int u,int fa){
size[u]=1,f[u]=fa,dis[u]=dis[fa]+1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa){
continue;
}
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[son[u]]){
son[u]=v;
}
}
}
void dfs2(int u,int tp){
ti[u]=++tot,pos[ti[u]]=w[u],top[u]=tp;
if(!son[u]){
return;
}
dfs2(son[u],tp);
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==f[u]||v==son[u]){
continue;
}
dfs2(v,v);
}
}
void Change(int x,int qx,int qy,int y){
int l=tree[x].l,r=tree[x].r;
if(l>=qx&&r<=qy){
tree[x].sum=(tree[x].sum+(r-l+1)*y)%mod;
tree[x].add=(tree[x].add+y)%mod;
return;
}
if(tree[x].add){
Pushdown(x);
}
int mid=(l+r)/2;
if(qy<=mid){
Change(ls(x),qx,qy,y);
}
else if(qx>mid){
Change(rs(x),qx,qy,y);
}
else{
Change(ls(x),qx,mid,y),Change(rs(x),mid+1,qy,y);
}
Pushup(x);
}
ll Query(int k,int qx,int qy){
int l=tree[k].l,r=tree[k].r;
if(l>=qx&&r<=qy){
return tree[k].sum;
}
if(tree[k].add){
Pushdown(k);
}
int mid=(l+r)/2;
if(qy<=mid){
return Query(ls(k),qx,qy);
}
if(qx>mid){
return Query(rs(k),qx,qy);
}
return (Query(ls(k),qx,mid)+Query(rs(k),mid+1,qy))%mod;
}
void TreeChange(int x,int y,int k){
while(top[x]!=top[y]){
if(dis[top[x]]<dis[top[y]]){
swap(x,y);
}
Change(1,ti[top[x]],ti[x],k);
x=f[top[x]];
}
if(dis[top[x]]>dis[top[y]]){
swap(x,y);
}
Change(1,ti[x],ti[y],k);
}
ll TreeQuery(int x,int y){
ll res=0;
while(top[x]!=top[y]){
if(dis[top[x]]<dis[top[y]]){
swap(x,y);
}
res=(res+Query(1,ti[top[x]],ti[x]))%mod;
x=f[top[x]];
}
if(dis[top[x]]>dis[top[y]]){
swap(x,y);
}
res=(res+Query(1,ti[x],ti[y]))%mod;
return res;
}
int main(){
n=read(),m=read(),r=read(),mod=read();
for(int i=1;i<=n;i++){
w[i]=read();
}
for(int i=1;i<n;i++){
x=read(),y=read();
add(x,y),add(y,x);
}
dfs1(r,0),dfs2(r,r),Build(1,1,n);
while(m--){
op=read();
if(op==1){
x=read(),y=read(),z=read();
TreeChange(x,y,z%mod);
}
if(op==2){
x=read(),y=read();
printf("%lld\n",TreeQuery(x,y));
}
if(op==3){
x=read(),z=read();
Change(1,ti[x],ti[x]+size[x]-1,z%mod);
}
if(op==4){
x=read();
printf("%lld\n",Query(1,ti[x],ti[x]+size[x]-1));
}
}
return 0;
}