1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
| #include<iostream> #include<cstdio> using namespace std; typedef long long LL; int head[100005],vet[200005],nxt[200005],num; int fa[100005],son[100005],sz[100005]; int depth[100005],top[100005]; int idx[100005],cnt; int a[100005],b[100005]; LL sum[400005],tag[400005]; int n,m,root,P; inline void addedge(int x,int y) { num++;vet[num]=y;nxt[num]=head[x];head[x]=num; num++;vet[num]=x;nxt[num]=head[y];head[y]=num; } void dfs1(int x,int ff,int dep) { depth[x]=dep;fa[x]=ff;sz[x]=1; int mx=0; for (int e=head[x];e;e=nxt[e]) { int v=vet[e]; if (ff==v) continue; dfs1(v,x,dep+1); sz[x]+=sz[v]; if (sz[v]>mx) mx=sz[v],son[x]=v; } } void dfs2(int x,int tp) { idx[x]=++cnt; b[cnt]=a[x]%P; top[x]=tp; if (!son[x]) return; dfs2(son[x],tp); for (int e=head[x];e;e=nxt[e]) if (!idx[vet[e]]) dfs2(vet[e],vet[e]); } void build(int l,int r,int pp) { if (l==r) { sum[pp]=b[l]; return; } int mid=(l+r)>>1; build(l,mid,pp<<1); build(mid+1,r,pp<<1|1); sum[pp]=(sum[pp<<1]+sum[pp<<1|1])%P; } inline void pushdown(int l,int r,int pp) { if (!tag[pp]) return; if (l==r) {tag[pp]=0;return;} int mid=(l+r)>>1; sum[pp<<1]=(sum[pp<<1]+tag[pp]*(mid-l+1))%P; tag[pp<<1]=(tag[pp<<1]+tag[pp])%P; sum[pp<<1|1]=(sum[pp<<1|1]+tag[pp]*(r-mid))%P; tag[pp<<1|1]=(tag[pp<<1|1]+tag[pp])%P; tag[pp]=0; } LL query(int l,int r,int pp,int ll,int rr) { if (l==ll && r==rr) return sum[pp]; pushdown(l,r,pp); int mid=(l+r)>>1; if (mid>=rr) return query(l,mid,pp<<1,ll,rr); else if (mid<ll) return query(mid+1,r,pp<<1|1,ll,rr); else return (query(l,mid,pp<<1,ll,mid)+query(mid+1,r,pp<<1|1,mid+1,rr))%P; } void update(int l,int r,int pp,int ll,int rr,int v) { if (l==ll && r==rr) { sum[pp]=(sum[pp]+(LL)(r-l+1)*v)%P; tag[pp]=(tag[pp]+v)%P; return; } pushdown(l,r,pp); int mid=(l+r)>>1; if (mid>=rr) update(l,mid,pp<<1,ll,rr,v); else if (mid<ll) update(mid+1,r,pp<<1|1,ll,rr,v); else update(l,mid,pp<<1,ll,mid,v),update(mid+1,r,pp<<1|1,mid+1,rr,v); sum[pp]=(sum[pp<<1]+sum[pp<<1|1])%P; } inline LL pathsum(int x,int y) { LL ans=0; while (top[x]!=top[y]) { if (depth[top[x]]<depth[top[y]]) swap(x,y); ans=(ans+query(1,n,1,idx[top[x]],idx[x]))%P; x=fa[top[x]]; } if (depth[x]>depth[y]) swap(x,y); ans=(ans+query(1,n,1,idx[x],idx[y]))%P; return ans; } inline void pathadd(int x,int y,int v) { while (top[x]!=top[y]) { if (depth[top[x]]<depth[top[y]]) swap(x,y); update(1,n,1,idx[top[x]],idx[x],v); x=fa[top[x]]; } if (depth[x]>depth[y]) swap(x,y); update(1,n,1,idx[x],idx[y],v); } int main() { cin >> n >> m >> root >> P; for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); addedge(x,y); } dfs1(root,0,1); dfs2(root,root); build(1,n,1); while (m--) { int op,x,y,z; scanf("%d",&op); if (op==1) { scanf("%d%d%d",&x,&y,&z); pathadd(x,y,z); } if (op==2) { scanf("%d%d",&x,&y); printf("%lld\n",pathsum(x,y)); } if (op==3) { scanf("%d%d",&x,&z); update(1,n,1,idx[x],idx[x]+sz[x]-1,z%P); } if (op==4) { scanf("%d",&x); printf("%lld\n",query(1,n,1,idx[x],idx[x]+sz[x]-1)); } } return 0; }
|