- 分享
- 2017-11-02 15:27:43 @
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int M = 100005;
const int N = 100005;
int n, m, root, opt, x, y, u, v;
LL a[N], z, MOD;
struct Edge{
int nxt, to;
}edge[M<<1];
int head[N], edge_num;
void add_edge(int from, int to){
edge[++edge_num].nxt = head[from];
edge[edge_num].to = to;
head[from] = edge_num;
}
int fa[N], dep[N], sz[N], son[N];
void dfs(int x, int f, int depth){
fa[x] = f, dep[x] = depth, sz[x] = 1, son[x] = 0;
for(int i = head[x]; i; i = edge[i].nxt){
if(edge[i].to == f) continue;
dfs(edge[i].to, x, depth+1);
sz[x] += sz[edge[i].to];
if(!son[x] || sz[edge[i].to] > sz[son[x]]) son[x] = edge[i].to;
}
}
int belong[N], start[N], end[N], dfs_clock, func[N];
void dfs(int x, int top){
start[x] = ++dfs_clock, func[dfs_clock] = x;
belong[x] = top;
if(son[x]) dfs(son[x], top);
for(int i = head[x]; i; i = edge[i].nxt){
if(edge[i].to == son[x] || edge[i].to == fa[x]) continue;
dfs(edge[i].to, edge[i].to);
}
end[x] = dfs_clock;
}
#define lid id<<1
#define rid id<<1|1
#define mid ((tr[id].l+tr[id].r)>>1)
#define len(id) (tr[id].r - tr[id].l + 1)
struct seg_tree{
int l, r;
LL lazy, sum;
}tr[N<<2];
void pushup(int id){
tr[id].sum = tr[lid].sum + tr[rid].sum;
}
void pushdown(int id){
if(tr[id].l != tr[id].r && tr[id].lazy != 0){
LL t = tr[id].lazy;
(tr[lid].lazy += t) %= MOD;
(tr[lid].sum += len(lid) * t) %= MOD;
(tr[rid].lazy += t) %= MOD;
(tr[rid].sum += len(rid) * t) %= MOD;
tr[id].lazy = 0;
}
}
void build(int id, int l, int r){
tr[id].l = l, tr[id].r = r;
tr[id].lazy = 0;
if(tr[id].l == tr[id].r){
tr[id].sum = a[func[l]] % MOD;
return;
}
build(lid, l, mid);
build(rid, mid+1, r);
pushup(id);
}
void add(int id, int l, int r, LL val){
pushdown(id);
if(tr[id].l == l && tr[id].r == r){
(tr[id].lazy += val) %= MOD;
(tr[id].sum += len(id) * val) %= MOD;
return;
}
if(r <= mid) add(lid, l, r, val);
else if(l > mid) add(rid, l, r, val);
else add(lid, l, mid, val), add(rid, mid+1, r, val);
pushup(id);
}
LL query(int id, int l, int r){
pushdown(id);
if(tr[id].l == l && tr[id].r == r)
return tr[id].sum % MOD;
if(r <= mid) return query(lid, l, r);
else if(l > mid) return query(rid, l, r);
else return (query(lid, l, mid) + query(rid, mid+1, r)) % MOD;
}
void Add_link(int u, int v, LL val){
while(belong[u] != belong[v]){
if(dep[belong[u]] < dep[belong[v]]) swap(u, v);
add(1, start[belong[u]], start[u], val);
u = fa[belong[u]];
}
if(dep[u] < dep[v]) swap(u, v);
add(1, start[v], start[u], val);
}
LL Query_link(int u, int v){
LL res = 0;
while(belong[u] != belong[v]){
if(dep[belong[u]] < dep[belong[v]]) swap(u, v);
(res += query(1, start[belong[u]], start[u])) %= MOD;
u = fa[belong[u]];
}
if(dep[u] < dep[v]) swap(u, v);
(res += query(1, start[v], start[u])) %= MOD;
return (res + MOD) % MOD;
}
void Add_sub(int u, LL val){
add(1, start[u], end[u], val);
}
LL Query_sub(int u){
return query(1, start[u], end[u]);
}
int main(){
scanf("%d%d%d%lld", &n, &m, &root, &MOD);
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
for(int i = 1; i < n; i++){
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
dfs(root, 0, 1);
dfs(root, root);
build(1, 1, n);
while(m--){
scanf("%d", &opt);
if(opt == 1){
scanf("%d%d%lld", &x, &y, &z);
Add_link(x, y, z);
}
else if(opt == 2){
scanf("%d%d", &x, &y);
printf("%lld\n", Query_link(x, y));
}
else if(opt == 3){
scanf("%d%lld", &x, &z);
Add_sub(x, z);
}
else if(opt == 4){
scanf("%d", &x);
printf("%lld\n", Query_sub(x));
}
}
return 0;
}
0 条评论
目前还没有评论...