1 #include <stdio.h> 2 #include <cstring> 3 #include <iostream> 4 #include <string> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #include <math.h> 9 #include <map> 10 11 #define LL long long 12 using namespace std; 13 const int maxn = 2e5 + 10; 14 15 struct Edge{ 16 int to,next; 17 }edge[maxn]; 18 19 int tot,head[maxn]; 20 21 void add_edge(int u,int v){ 22 edge[tot] = Edge{v,head[u]}; 23 head[u] = tot++; 24 edge[tot] = Edge{u,head[v]}; 25 head[v] = tot++; 26 } 27 28 int mod; 29 int v[maxn]; // 结点权值 30 int fa[maxn]; // 父亲 31 intDEP [MAXN]; // depth 32 int SIZ [MAXN]; // Size 33 is int Son [MAXN]; // weight son 34 is 35 // first pass depth can be dfs, father, size, weight son 36 void DFS1 ( int u, int F) { // u is the current node, f u is the father of 37 [ FA [u] = F; 38 is DEP [u] = DEP [F] + . 1 ; 39 SIZ [u] = . 1 ; 40 int MAXSIZE = - . 1 ; // Analyzing a temporary variable is not a son weight 41 is for( Int I = head [U]; ~ I; I = Edge [I] .next) { 42 is int V = Edge [I] .to; 43 is IF (V == F) // if it is not the father affirmative 44 Continue ; 45 DFS1 (V, U); 46 is SIZ [U] + = SIZ [V]; 47 IF (SIZ [V]> MAXSIZE) { 48 MAXSIZE = SIZ [V]; 49 Son [U] = V; / / U son is heavy V 50 } 51 is } 52 is } 53 is 54 is int Tim; //Timestamp counter 55 int DFN [MAXN]; // stamp 56 is int Top [MAXN]; // the top of the heavy chain 57 is int W [MAXN]; // node weights dfs sequence 58 59 void DFS2 ( int U, int T) { // U is the current node, t is the current node is the head of the heavy chain 60 DFN [U] = ++ Tim; 61 is Top [U] = T; 62 is W [Tim] = V [U] ; 63 IF (! son [U]) // If heavy son does not exist, then it is a leaf node, exit 64- return ; 65 DFS2 (Son [U], T); 66 for ( int I = head [U]; ~ I; I = Edge [I] .next) { 67 int V = Edge [I] .to; 68 IF (V = FA = [U] || v == son [U]) // up traversal certainly not, because the front dfs2 has traversed a heavy son here so did not need the 69 the Continue ; 70 dfs2 (v, v) ; // this time the son is certainly light 71 is } 72 } 73 is 74 struct segment_tree { 75 int L, R & lt, Val; 76 int the lazy; 77 } Tree [* MAXN . 4 ]; 78 79 void pushup(int nod){ 80 tree[nod].val = (tree[nod<<1].val + tree[(nod<<1)+1].val) % mod; 81 } 82 83 void pushdown(int nod){ 84 tree[nod<<1].lazy += tree[nod].lazy; 85 tree[(nod<<1)+1].lazy += tree[nod].lazy; 86 tree[nod<<1].val += (tree[nod<<1].r-tree[nod<<1].l + 1) * tree[nod].lazy % mod; 87 tree[(nod<<1)+1].val += (tree[(nod<<1)+1].r-tree[(nod<<1)+1].l+1) * tree[nod].lazy % mod; 88 tree[nod].lazy = 0; 89 } 90 91 void build(int l,int r,int nod=1){ 92 tree[nod].l = l; 93 tree[nod].r = r; 94 if (l == r){ 95 tree[nod].lazy = 0; 96 tree[nod].val = w[l] % mod; 97 return ; 98 } 99 int mid = (l+r)>>1; 100 build(l,mid,nod<<1); 101 build(mid+1,r,(nod<<1)+1); 102 pushup(nod); 103 } 104 105 void modify(int x,int y,int z,int k=1){ 106 int l = tree[k].l, r = tree[k].r; 107 if (x<= l && y>=r){ 108 tree[k].lazy += z; 109 tree[k].val += (r-l+1) * z; 110 tree[k].val %= mod; 111 return ; 112 } 113 if (tree[k].lazy) 114 pushdown(k); 115 int mid = (l+r)>>1; 116 if (x<=mid){ 117 modify(x,y,z,k<<1); 118 } 119 if (y>mid){ 120 modify(x,y,z,(k<<1)+1); 121 } 122 pushup(k); 123 } 124 125 int query(int x,int y,int k=1){ 126 int l = tree[k].l,r = tree[k].r; 127 if (x<=l && y>=r){ 128 return tree[k].val; 129 } 130 if (tree[k].lazy){ 131 pushdown(k); 132 } 133 int sum = 0,mid = (l+r)>>1; 134 if (x <= mid){ 135 sum += query(x,y,k<<1); 136 } 137 if (y > mid){ 138 sum += query(x,y,(k<<1)+1); 139 } 140 return sum % mod; 141 } 142 143 void mchain(int x,int y,int Z) { // node x-> node on the shortest path to all nodes y plus Z 144 Z% = MOD; 145 the while ! (Top [X] = Top [y]) { 146 IF (DEP [Top [ X]] < DEP [Top [Y]]) 147 the swap (X, Y); 148 Modify (DFN [Top [X]], DFN [X], Z); 149 X = FA [Top [X]]; 150 } 151 IF (DEP [X]> DEP [Y]) 152 the swap (X, Y); 153 Modify (DFN [X], DFN [Y], Z); 154 } 155 156 int QChain ( int X, inty) { // query to x values of all nodes in the shortest path and the y nodes 157 int RET = 0 ; 158 the while ! (Top [x] = Top [y]) { 159 IF (DEP [Top [x] ] < DEP [Top [Y]]) 160. the swap (X, Y); 161 RET + = Query (DFN [Top [X]], DFN [X]); 162 X = FA [Top [X]]; 163 } 164 is IF (DEP [X]> DEP [Y]) 165 the swap (X, Y); 166 RET + = Query (DFN [X], DFN [Y]); 167 is return RET% MOD; 168 } 169 170. void MSON ( int x, int Z) { // for all nodes within the x value is a root node of the subtree are coupled Z 171 is Modify (DFN [x], DFN [x] + SIZ [x] - . 1 , Z); // must be continuous 172 } 173 174 int qson ( int x) { // for all nodes within the x value as the root node of the subtree and 175 return Query (DFN [x], DFN [x] + SIZ [X] - . 1 ); 176 } 177 178 179 int main () { 180 [ Memset (head, - . 1 , the sizeof (head)); 181 int n,m,r; 182 scanf("%d%d%d%d",&n,&m,&r,&mod); 183 for (int i=1;i<=n;i++){ 184 scanf("%d",&v[i]); 185 } 186 for (int i=1;i<n;i++){ 187 int u,v; 188 scanf("%d%d",&u,&v); 189 add_edge(u,v); 190 } 191 dfs1(r,r); 192 dfs2(r,r); 193 build(1,n); 194 while (m--){ 195 int opt,x,y,z; 196 scanf("%d",&opt); 197 switch(opt){ 198 case 1: 199 scanf("%d%d%d",&x,&y,&z); 200 mchain(x,y,z); 201 break; 202 case 2: 203 scanf("%d%d",&x,&y); 204 printf("%d\n",qchain(x,y)); 205 break; 206 case 3: 207 scanf("%d%d",&x,&z); 208 mson(x,z); 209 break; 210 case 4: 211 scanf("%d",&x); 212 printf("%d\n",qson(x)); 213 break; 214 } 215 } 216 return 0; 217 }