#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm> #define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using namespace std;
const int maxn = ;
int P;
typedef long long ll; struct Edge {
int to, next;
}edges[maxn*];
int head[maxn], tot;
int n;
ll w[maxn];
int fa[maxn], son[maxn], siz[maxn], dep[maxn];
int top[maxn], id[maxn], rk[maxn], cnt;
// son[u]: u的重儿子
// top[u]: u所在链的顶端节点
//
// id[u]: 树链剖分后节点的新编号
// rk[u]: dfs编号对应的节点 rk[id[u]] = u
// cnt : dfs序 void add(int u, int v) {
edges[++tot].to = v;
edges[tot].next = head[u];
head[u] = tot;
} // 求fa, siz, dep, son
void dfs1(int u) {
siz[u] = ;
for(int i=head[u];i;i=edges[i].next) {
int v = edges[i].to;
if(v==fa[u]) continue; fa[v] = u;
dep[v] = dep[u] + ;
dfs1(v);
siz[u] += siz[v]; if(siz[v]>siz[son[u]])
son[u] = v;
}
} // 连接重链
void dfs2(int u, int topf) {
id[u] = ++cnt;
rk[cnt] = u; top[u] = topf;
if(!son[u])
return; dfs2(son[u], topf); // 重链先dfs,保证重链上各节点dfs序连续 for(int i=head[u];i;i=edges[i].next) {
int v = edges[i].to;
if(v!=fa[u] && v!=son[u]) // 不是重儿子,轻链
dfs2(v, v);
}
} /*
操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和 操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z 操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和
*/ ll sum[maxn*], lazy[maxn*]; void build(int rt, int l, int r) {
if(l!=r) {
int mid = (l+r)/;
build(lson);
build(rson);
sum[rt] = (sum[rt<<] + sum[rt<<|]) % P;
} else {
sum[rt] = w[rk[l]];
lazy[rt] = ;
}
}
void pushDown(int rt, int len) {
if(lazy[rt]) {
(sum[rt<<] += (len-(len>>)) * lazy[rt] % P) %= P;
(sum[rt<<|] += (len>>) * lazy[rt] % P) %= P; (lazy[rt<<] += lazy[rt]) %= P;
(lazy[rt<<|] += lazy[rt]) %= P;
lazy[rt] = ;
}
} void update(int rt, int l, int r, int L, int R, ll add) {
if(L<=l && R>=r) {
(lazy[rt] += add) %= P;
(sum[rt] += (r-l+)*add) %= P;
return;
} int mid = (l+r)/;
pushDown(rt, r-l+); if(L<=mid)
update(lson, L, R, add);
if(R>mid)
update(rson, L, R, add); sum[rt] = (sum[rt<<] + sum[rt<<|]) % P;
} ll query(int rt, int l, int r, int L, int R) {
if(L<=l && R>=r) return sum[rt]; ll res = ;
int mid = (l+r)/;
pushDown(rt, r-l+); if(L<=mid) res += query(lson, L, R) % P;
if(R>mid) res += query(rson, L, R) % P;
return res % P;
} // 操作1
void updatePath(int x, int y, ll z) {
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) swap(x, y);
update(, , n, id[top[x]], id[x], z);
x = fa[top[x]];
}
if(dep[x]>dep[y]) swap(x, y);
update(, , n, id[x], id[y], z);
} // 操作3
void updateSon(int x, ll z) {
update(, , n, id[x], id[x]+siz[x]-, z);
} // 操作2
ll queryPath(int x, int y) {
ll res = ;
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) swap(x, y);
res = (res + query(, , n, id[top[x]], id[x])) % P;
x = fa[top[x]];
}
if(dep[x]>dep[y]) swap(x, y);
res = (res + query(, , n, id[x], id[y])) % P;
return res;
} // 操作4
ll qeurySon(int x) {
return query(, , n, id[x], id[x]+siz[x]-);
} int main() {
int M, R;
cin>>n>>M>>R>>P;
for(int i=;i<=n;i++) {
scanf("%lld", &w[i]);
}
for(int i=;i<n-;i++) {
int u, v;
scanf("%d %d", &u, &v);
add(u, v);
add(v, u);
} dfs1(R);
dfs2(R, R); build(, , n); while(M--) {
int op, x, y;
ll z;
scanf("%d", &op);
if(op==) {
scanf("%d %d %lld", &x, &y, &z);
updatePath(x, y, z);
} else if(op==) {
scanf("%d %d", &x, &y);
printf("%lld\n", queryPath(x, y));
} else if(op==) {
scanf("%d %lld", &x, &z);
updateSon(x, z);
} else {
scanf("%d", &x);
printf("%lld\n", qeurySon(x));
} }
return ;
}

最新文章

  1. mysql添加一个用户
  2. c# 文件夾操作
  3. 对thinkphp静态模板表单提交的理解
  4. 前端程序员:月薪 5K 到 5 万,我干了啥(转)
  5. 安装linux操作系统--浪潮服务器
  6. SQL Server 字符串函数
  7. ASP.Net 使用SqlBulkCopy批量插入
  8. django 学习-1
  9. WebStorm的compass配置
  10. java类和对象之间的差
  11. Size Balanced Tree(SBT) 模板
  12. 【转】javascript中的LHS与RHS
  13. EJB3+JBoss5+Myeclipse9创建HelloWorld实例
  14. DCGAN 代码简单解读
  15. Nginx 一个高性能的HTTP和反向代理服务器
  16. springboot后台运行
  17. GitLab管理之 - Gitlab 用户管理
  18. linux java报错汇总
  19. ecshop 订单状态
  20. Hadoop学习之路(十八)MapReduce框架Combiner分区

热门文章

  1. $.extend() $.fn.extend()
  2. 转 直接在浏览器运行Python代码
  3. C++ 短信验证码/通知 - 代码示例
  4. GlobalExceptionHandler 捕获抛出的异常,返回特定值给前端
  5. Django使用步骤
  6. NX二次开发-创建圆弧(圆心-半径)UF_CURVE_create_arc
  7. NX二次开发-UFUN工程图表格注释获取某一列的tag函数UF_TABNOT_ask_nth_column
  8. slot 的简单用法
  9. 第36讲 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景
  10. LightOJ 1245 - Harmonic Number (II)