#include <iostream>
#include <cstdio>
using namespace std ;
#define maxn int(1e5+5)
struct Node {
int fa ;//父亲
int son ;//重儿子
int size ;//大小
int top ;//当前结点
int dfn ;//时间戳
int deep ;//深度
}tree[maxn];//树链剖分
int w[maxn] ;//结点权值dfs序
int tim ;//时间戳计数器tim
int v[maxn] ;//所有结点的权值
struct Edge
{
int to , nxt ;
}edge[2*maxn] ;
int tot , head[maxn] ;
inline void add(int u , int v) {
edge[++tot]=(Edge){v,head[u]} ;
head[u] = tot ;
}
void dfs1(int u,int fa) {
tree[u].fa = fa ;
tree[u].deep = tree[fa].deep + 1 ;
tree[u].size = 1 ;
int maxsize=-1 ;
for ( int i = head[u] ; i ; i = edge[i].nxt)
{
int v = edge[i].to ;
if(v==fa)//回溯了
continue ;
dfs1(v,u) ;
tree[u].size += tree[v].size ;
if(tree[v].size>maxsize) {
maxsize = tree[v].size ;
tree[u].son = v ;
}
}
}//第一次dfs:求重儿子、深度、子树大小
void dfs2(int u , int t) {//u:当前结点,t:重链top
tree[u].dfn = ++tim ;
tree[u].top = t ;
w[tim] = v[u] ;
if(!tree[u].son) return ;//没儿子->bye
dfs2(tree[u].son,t) ;
for ( int i = head[u] ; i ; i = edge[i].nxt)
{
int v = edge[i].to ;
if(v==tree[u].fa||v==tree[u].son)
continue ;
dfs2(v,v) ;//从轻儿子开始的重链
}
}//第二次dfs:求时间戳
int mod;
struct node
{
int l, r, f, val;
} sgt[maxn * 4];//维护w数组线段树
inline int ls(int k) { return k << 1; }
inline int rs(int k) { return k << 1 | 1; }
inline void pushup(int k) { sgt[k].val = (sgt[ls(k)].val + sgt[rs(k)].val) % mod; }
inline void pushdown(int k)
{
sgt[ls(k)].f += sgt[k].f;
sgt[rs(k)].f += sgt[k].f;
sgt[ls(k)].val += (sgt[ls(k)].r - sgt[ls(k)].l + 1) * sgt[k].f % mod;
sgt[rs(k)].val += (sgt[rs(k)].r - sgt[rs(k)].l + 1) * sgt[k].f % mod;
sgt[k].f = 0;
}
void build(int l, int r, int k = 1)
{
sgt[k].l = l, sgt[k].r = r;
if (l == r)
{
sgt[k].val = w[l] % mod;
return;
}
int m = (l + r) >> 1;
build(l, m, ls(k));
build(m + 1, r, rs(k));
pushup(k);
}
void modify(int x, int y, int z, int k = 1)
{
int l = sgt[k].l, r = sgt[k].r;
if (x <= l && y >= r)
{
sgt[k].f += z;
sgt[k].val += (r - l + 1) * z;
sgt[k].val %= mod;
return;
}
if (sgt[k].f)
pushdown(k);
int m = (l + r) >> 1;
if (x <= m)
modify(x, y, z, ls(k));
if (y > m)
modify(x, y, z, rs(k));
pushup(k);
}
int query(int x, int y, int k = 1)
{
int l = sgt[k].l, r = sgt[k].r;
if (x <= l && y >= r)
return sgt[k].val;
if (sgt[k].f)
pushdown(k);
int sum = 0, m = (l + r) >> 1;
if (x <= m)
sum += query(x, y, ls(k));
if (y > m)
sum += query(x, y, rs(k));
return sum % mod;
}//72~132为线段树代码
inline void mson(int x,int z) {
modify(tree[x].dfn,
tree[x].dfn+tree[x].size-1,z%mod) ;
}//操作三
inline int qson(int x) {
return query(tree[x].dfn,
tree[x].dfn+tree[x].size-1) ;
}//操作四
void mchain(int x , int y,int z) {
z%=mod ;
while(tree[x].top!=tree[y].top)//不在同一重链
{
if(tree[tree[x].top].deep<
tree[tree[y].top].deep)
swap(x,y) ;
modify(tree[tree[x].top].dfn,tree[x].dfn,z) ;
x = tree[tree[x].top].fa ;
}
if(tree[x].deep>tree[y].deep)
swap(x,y) ;
modify(tree[x].dfn,tree[y].dfn,z) ;
}
int qchain(int x,int y) {
int res = 0 ;
while(tree[x].top!=tree[y].top) {
if(tree[tree[x].top].deep<
tree[tree[y].top].deep)
swap(x,y) ;
res+=query(tree[tree[x].top].dfn,
tree[x].dfn) ;
x = tree[tree[x].top].fa ;
}
if(tree[x].deep>tree[y].deep)
swap(x,y) ;
res+=query(tree[x].dfn,tree[y].dfn) ;
return res%mod ;
}
int main ( ) {
#ifndef ONLINE_JUDGE
// freopen("input.in","r",stdin) ;
// freopen("output.out","w",stdout) ;
#endif
int n , m , r ;
cin >> n >> m >> r >> mod ;
for ( int i = 1 ; i <= n ; i++ ) {
cin >> v[i] ;
v[i]%=mod ;
}
for ( int i = 1 ; i < n ; i ++ ) {
int u , v ;
cin >> u >> v ;
add(u,v) ;
add(v,u) ;
}
dfs1(r,r) ;
dfs2(r,r) ;
build(1,n) ;
while(m--) {
int opt , x , y , z ;
cin >> opt ;
switch(opt) {
case 1:cin >> x >> y >> z ;
mchain(x,y,z) ;
break ;
case 2:cin >> x >> y ;
cout << qchain(x,y) << endl ;
break ;
case 3:cin >> x >> z ;
mson(x,y) ;
break ;
case 4:cin >> x ;
cout << qson(x) << endl ;
break ;
}
}
#ifndef ONLINE_JUDGE
system("pause") ;
#endif
return 0 ;
}
样例WA了,求助求助求助(拜托