如题,鄙人代码如下。多谢各位大佬出手相助!
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#define thisSon edge[i].destiVertex
#define xTop vertex[x].chainTop
#define yTop vertex[y].chainTop
using namespace std;
const int MaxN = 1000005;
int n, m, root, mod, res, finalVal[MaxN];
struct Vertex{
int val, father, depth, subtreeSize, heavySon, chainTop, DFN;
}vertex[MaxN];
struct Edge{
int destiVertex, nextEdge;
}edge[MaxN * 2];
struct SegmentTree{
int data, addTag, l, r;
}seg[MaxN * 4];
int tot, head[MaxN], cntDFN;
inline void AddEdge(int u,int v){
tot++;
edge[tot].destiVertex = v;
edge[tot].nextEdge = head[u];
head[u] = tot;
}
inline void PassTag(int x){
seg[x*2].addTag += seg[x].addTag;
seg[x*2+1].addTag += seg[x].addTag;
seg[x*2].data = (seg[x*2].data + seg[x].addTag * (seg[x*2].r - seg[x*2].l + 1) % mod) % mod;
seg[x*2+1].data = (seg[x*2+1].data + seg[x].addTag * (seg[x*2+1].r - seg[x*2+1].l + 1) % mod) % mod;
seg[x].addTag = 0;
}
inline void Build(int x,int l,int r){
seg[x].l = l;
seg[x].r = r;
if(l == r){
seg[x].data = finalVal[l];
if(seg[x].data > mod) seg[x].data %= mod;
return;
}
int mid = (l + r) / 2;
Build(x*2, l, mid);
Build(x*2+1, mid+1, r);
seg[x].data = (seg[x*2].data + seg[x*2+1].data) % mod;
}
inline void Ask(int x, int l, int r){
if(l <= seg[x].l && r >= seg[x].r){
res = (res + seg[x].data) % mod;
return;
}
else{
if(seg[x].addTag) PassTag(x);
int mid = (seg[x].l + seg[x]. r) / 2;
if(l <= mid) Ask(x*2, l, r);
if(r > mid) Ask(x*2+1, l, r);
}
}
inline void Addition(int x, int l, int r, int z){
if(l <= seg[x].l && r >= seg[x].r){
seg[x].addTag += z;
seg[x].data = (seg[x].data + z * (seg[x].r - seg[x].l + 1)) % mod;
}
else{
if(seg[x].addTag) PassTag(x);
int mid = (seg[x].l + seg[x].r) / 2;
if(l <= mid) Addition(x*2, l, r, z);
if(r > mid) Addition(x*2+1, l, r, z);
seg[x].data = (seg[x*2].data + seg[x*2+1].data) % mod;
}
}
inline int WayAsk(int x,int y){
int ans=0;
while(xTop != yTop){
if(vertex[xTop].depth < vertex[yTop].depth) swap(x, y);
res = 0;
Ask(1, vertex[xTop].DFN, vertex[x].DFN);
ans += res;
ans %= mod;
x = vertex[xTop].father;
}
if(vertex[x].depth > vertex[y].depth) swap(x, y);
res = 0;
Ask(1, vertex[x].DFN, vertex[y].depth);
ans += res;
return ans % mod;
}
inline void WayAdd(int x,int y,int k){
k %= mod;
while(xTop != yTop){
if(vertex[xTop].depth < vertex[yTop].depth) swap(x,y);
Addition(1, vertex[xTop].DFN, vertex[x].DFN,k);
x = vertex[xTop].father;
}
if(vertex[x].depth > vertex[y].depth) swap(x, y);
Addition(1, vertex[x].DFN, vertex[y].DFN, k);
}
inline int SubtreeAsk(int x){
res = 0;
Ask(1, vertex[x].DFN, vertex[x].DFN + vertex[x].subtreeSize - 1);
return res;
}
inline void SubtreeAdd(int x,int k){
Addition(1, vertex[x].DFN, vertex[x].DFN + vertex[x].subtreeSize - 1, k);
}
inline void DFS1(int x){
vertex[x].heavySon = -1;
vertex[x].subtreeSize = 1;
for(int i = head[x]; i; i = edge[i].nextEdge){
if(thisSon == vertex[x].father) continue;
vertex[thisSon].depth = vertex[x].depth + 1;
vertex[thisSon].father = x;
DFS1(thisSon);
vertex[x].subtreeSize += vertex[thisSon].subtreeSize;
if(vertex[x].heavySon == -1 || vertex[thisSon].subtreeSize > vertex[vertex[x].heavySon].subtreeSize) vertex[x].heavySon = thisSon;
}
}
inline void DFS2(int x, int top){
vertex[x].DFN = ++cntDFN;
finalVal[cntDFN] = vertex[x].val;
vertex[x].chainTop = top;
if(vertex[x].heavySon == -1) return;
DFS2(vertex[x].heavySon, top);
for(int i = head[x]; i; i = edge[i].nextEdge){
if(thisSon == vertex[x].father || thisSon == vertex[x].heavySon) continue;
DFS2(thisSon, thisSon);
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&root,&mod);
for(int i = 1; i <= n; i++) scanf("%d",&vertex[i].val);
for(int i = 1; i < n; i++){
int u, v;
scanf("%d%d",&u,&v);
AddEdge(u, v);
AddEdge(v, u);
}
vertex[root].father = 0;
vertex[root].depth = 1;
DFS1(root);
DFS2(root, root);
Build(1,1,n);
while(m--){
int op, x, y, z;
scanf("%d",&op);
if(op == 1){
scanf("%d%d%d",&x,&y,&z);
WayAdd(x, y, z);
}
if(op == 2){
scanf("%d%d",&x,&y);
printf("%d\n",WayAsk(x, y));
}
if(op == 3){
scanf("%d%d",&x,&z);
SubtreeAdd(x, z);
}
if(op == 4){
scanf("%d",&x);
printf("%d\n",SubtreeAsk(x));
}
}
}