You ye Jiu yuan is the daughter of the Great GOD Emancipator. And when she becomes an adult, she will be queen of Tusikur, so she wanted to travel the world while she was still young. In a country, she found a small pub called Whitehouse. Just as she was about to go in for a drink, the boss Carola appeared. And ask her to solve this problem or she will not be allowed to enter the pub. The problem description is as follows:

There is a tree with nn nodes, each node ii contains weight a[i]a[i], the initial value of a[i]a[i] is 00. The root number of the tree is 11. Now you need to do the following operations:

1)1) Multiply all weight on the path from uu to vv by xx

2)2) For all weight on the path from uu to vv, increasing xx to them

3)3) For all weight on the path from uu to vv, change them to the bitwise NOT of them

4)4) Ask the sum of the weight on the path from uu to vv

The answer modulo 2^{64}264.

Jiu Yuan is a clever girl, but she was not good at algorithm, so she hopes that you can help her solve this problem. Ding\backsim\backsim\backsim∽∽∽

The bitwise NOT is a unary operation that performs logical negation on each bit, forming the ones' complement of the given binary value. Bits that are 00 become 11, and those that are 11 become 00. For example:

NOT 0111 (decimal 7) = 1000 (decimal 8)

NOT 10101011 = 01010100

Input

The input contains multiple groups of data.

For each group of data, the first line contains a number of nn, and the number of nodes.

The second line contains (n - 1)(n−1) integers b_ibi, which means that the father node of node (i +1)(i+1) is b_ibi.

The third line contains one integer mm, which means the number of operations,

The next mm lines contain the following four operations:

At first, we input one integer opt

1)1) If opt is 11, then input 33 integers, u, v, xu,v,x, which means multiply all weight on the path from uu to vv by xx

2)2) If opt is 22, then input 33 integers, u, v, xu,v,x, which means for all weight on the path from uu to vv, increasing xx to them

3)3) If opt is 33, then input 22 integers, u, vu,v, which means for all weight on the path from uu to vv, change them to the bitwise NOT of them

4)4) If opt is 44, then input 22 integers, u, vu,v, and ask the sum of the weights on the path from uu to vv

1 \le n,m,u,v \le 10^51≤n,m,u,v≤105

1 \le x < 2^{64}1≤x<264

Output

For each operation 44, output the answer.

样例输入复制

7
1 1 1 2 2 4
5
2 5 6 1
1 1 6 2
4 5 6
3 5 2
4 2 2
2
1
4
3 1 2
4 1 2
3 1 1
4 1 1

样例输出复制

5
18446744073709551613
18446744073709551614
0

题目来源

​ACM-ICPC 2018 焦作赛区网络预赛​

 

题意:

给你一棵树,你要支持如下操作:

1 u v x:在树上u到v路径上的所有点的值增加v
2 u v x:在树上u到v路径上的所有点的值乘v
3 u v:在树上u到v路径上的所有点的值按位取反
4 u v:查询u到v路径上的所有点权和
要求所有的操作对于2^64取模。

分析:

1,2,3都是金典操作,3为:~n=-(n+1)。

关于取模直接开ULL,溢出后自动取模。

关于取反操作:

~n=11111……1111-n

【2018焦作网络赛】Jiu Yuan Wants to Eat【树链剖分】_#define

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ULL;

const ULL INF=(ULL)0-(ULL)1;

const int N = 1e5+5;
int n, q, r;
int w[N];
int head[N], cnt;
int num;
int root[N];//保存结点 u 的父亲节点
int depth[N]; //保存结点 u 的深度值
int W_son[N];//保存重儿子
int size[N]; //保存以 u 为根的子树节点个数
int top[N];//保存当前节点所在链的顶端节点
int id[N];//保存树中每个节点剖分以后的新编号( DFS 的执行顺序)
int new_W[N]; //保存当前 dfs 标号在树中所对应的节点

struct Eddge
{
int nex, to;
Eddge(int a=-1, int b=0):nex(a), to(b) {}
} edge[N<<1];//这里卡了好久,一定要乘以2
void addEddge(int u, int v)
{

edge[cnt] = Eddge(head[u], v);
head[u] = cnt++;
}
void dfs1(int u, int fa, int deep)
{

depth[u] = deep;
root[u] = fa;
size[u] = 1;
int maxSon = -1;
for(int i=head[u]; i!=-1; i=edge[i].nex)
{
int v = edge[i].to;
if(v == fa)
continue;
dfs1(v, u, deep+1);
size[u] += size[v];
if(size[v] > maxSon)
{
maxSon = size[v];
W_son[u] = v;
}
}
}
void dfs2(int u, int topf)
{

id[u] = ++num;
new_W[num] = w[u];
top[u] = topf;
if(!W_son[u])
return;
dfs2(W_son[u], topf);
for(int i=head[u]; i!=-1; i=edge[i].nex)
{
int v = edge[i].to;
if(v == W_son[u] || v == root[u])
continue;
dfs2(v, v);
}
}

struct Node
{
int l;
int r;
ULL add;
ULL mul;//区间乘法标记
//ll rep;//区间修改标记
ULL sum;//存1次方,2次方和,3次方和,如果超时注意删除无用的
} tree[N<<2];

ULL sum;
void pushdown(int k)
{
/* if(tree[k].rep)
{
tree[k<<1].rep = tree[k<<1|1].rep = tree[k].rep;
tree[k<<1].mul = tree[k<<1|1].mul = 0;
tree[k<<1].add = tree[k<<1|1].add = tree[k].rep;
tree[k<<1].sum = tree[k].rep % MOD * (tree[k<<1].r - tree[k<<1].l + 1) % MOD;
tree[k<<1|1].sum = tree[k].rep % MOD * (tree[k<<1|1].r - tree[k<<1|1].l + 1) % MOD;

tree[k].rep = 0;
} */
if(tree[k].mul != 1)
{
tree[k<<1].add = tree[k<<1].add * tree[k].mul ;
tree[k<<1|1].add = tree[k<<1|1].add * tree[k].mul ;
tree[k<<1].mul = tree[k<<1].mul * tree[k].mul ;
tree[k<<1|1].mul = tree[k<<1|1].mul * tree[k].mul ;
tree[k<<1].sum = tree[k<<1].sum * tree[k].mul ;
tree[k<<1|1].sum = tree[k<<1|1].sum * tree[k].mul ;

tree[k].mul = 1;
}
if(tree[k].add)
{
tree[k<<1].add = (tree[k<<1].add + tree[k].add) ;
tree[k<<1|1].add = (tree[k<<1|1].add + tree[k].add) ;
tree[k<<1].sum = (tree[k<<1].sum + tree[k].add * (tree[k<<1].r - tree[k<<1].l + 1) ) ;
tree[k<<1|1].sum = (tree[k<<1|1].sum + tree[k].add * (tree[k<<1|1].r - tree[k<<1|1].l + 1) ) ;

tree[k].add = 0;
}
}
void pushup(int k)
{
tree[k].sum = (tree[k<<1].sum + tree[k<<1|1].sum) ;
}

void build(int k, int l, int r)
{
tree[k].l = l;
tree[k].r = r;
tree[k].add = 0;
tree[k].mul = 1;
//tree[k].rep = 0;

if(l == r)
{
tree[k].sum = 0;
return;
}
pushdown(k);
int mid = (l + r) >>1;
build(k<<1, l, mid);
build(k<<1|1, mid + 1, r);
pushup(k);
}
//dir=1,区间+;dir=2,区间乘;dir=3,区间修改
void interver(int k, int l, int r, ULL c, int dir)
{
if(tree[k].l >= l && tree[k].r <= r)
{
if(dir == 1)
{
tree[k].add = (tree[k].add + c);
tree[k].sum = (tree[k].sum + c * (tree[k].r - tree[k].l + 1)) ;
return;
}
else if(dir == 2)
{
tree[k].add = tree[k].add * c ;
tree[k].mul = tree[k].mul * c;
tree[k].sum = tree[k].sum * c ;
return;
}
/*
else if(dir == 3)
{
tree[k].add = 0;
tree[k].mul = 1;
tree[k].rep = c;
tree[k].sum = c * (tree[k].r - tree[k].l + 1) % MOD;
return;
} */
}
pushdown(k);
int mid = (tree[k].l + tree[k].r) >>1;
if(l <= mid)
interver(k<<1, l,r, c, dir);
if(mid < r)
interver(k<<1|1,l,r, c, dir);
pushup(k);
}
//sum求和,求表示sum=a[l]^c+a[l+1]^c......+a[r]^c
void query(int k, int l, int r)
{
//cout<<tree[k].l<<" "<<tree[k].r<<" "<<l<<" "<<r<<endl;
if(tree[k].l >= l && tree[k].r <= r)
{
sum = (sum + tree[k].sum) ;
return;
}
pushdown(k);
int mid = (tree[k].l + tree[k].r) >>1;
if(l <= mid)
query(k<<1, l,r);
if(mid < r)
query(k<<1|1, l,r);
pushup(k);
}
void update_range(int op,int x, int y, ULL val)
{
if(op==1)
op=2;
else
op=1;
while(top[x] != top[y])
{
if(depth[top[x]] < depth[top[y]])
swap(x, y);
interver(1, id[top[x]], id[x], val,op);
x = root[top[x]];
}
if(depth[x] > depth[y])
swap(x, y);
interver(1, id[x], id[y], val,op);
}

ULL Query_range(int x, int y)
{

ULL ans = 0;
while(top[x] != top[y])
{
if(depth[top[x]] < depth[top[y]])
swap(x, y);
sum=0;
query(1,id[top[x]], id[x]);
ans = (ans + sum);
x = root[top[x]];
}
if(depth[x] > depth[y])
swap(x, y);
sum=0;
query(1, id[x], id[y]);

ans = (ans + sum);
return ans;
}

void update_son(int x, int val)
{
interver(1, id[x], id[x]+size[x]-1, val,1);
}
int Query_son(int x)
{
sum=0;
query(1, id[x], id[x]+size[x]-1);
return sum;
}
void init()
{
cnt = num = 0;
memset(head, -1, sizeof(head));
memset(W_son, 0, sizeof(W_son));
}
int main()
{
while(scanf("%d", &n)!=EOF)
{
r=1;
init();


for(int i=2; i<=n; i++)
{
int e1=i,e2;
scanf("%d", &e2);
addEddge(e1, e2);
addEddge(e2, e1);
}

dfs1(r, r, 0);
dfs2(r, r);


build(1, 1, n);
scanf("%d",&q);
while(q--)
{
int op, x, y;
ULL z;
scanf("%d", &op);
if(op <= 2&&op>=1)
{
scanf("%d%d%llu", &x, &y, &z);
update_range(op, x, y, z);
}
else if(op == 3)
{
scanf("%d%d", &x, &y);
update_range(2,x,y,1);
update_range(1,x,y,-1);
}
else if(op == 4)
{
scanf("%d%d", &x, &y);
printf("%llu\n", Query_range(x, y));
}
// printf("############%llu\n", Query_range(1, 6));

}
}
return 0;
}

 

另一种线段树

 

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 1e5+5;
const ull INF=(ull)0-(ull)1;
int N, Q, cnt, head[maxN], root[maxN], depth[maxN], size[maxN], W_son[maxN], top[maxN], id[maxN], num;
ull tree[maxN<<2], lazy[maxN<<2], mult[maxN<<2];
struct Eddge
{
int nex, to;
Eddge(int a=-1, int b=0):nex(a), to(b) {}
}edge[maxN<<1];
void addEddge(int u, int v)
{
edge[cnt] = Eddge(head[u], v);
head[u] = cnt++;
}
void dfs1(int u, int fa, int deep)
{
root[u] = fa;
depth[u] = deep;
size[u] = 1;
int maxxSon = -1;
for(int i=head[u]; i!=-1; i=edge[i].nex)
{
int v = edge[i].to;
if(v == fa) continue;
dfs1(v, u, deep+1);
size[u] += size[v];
if(maxxSon < size[v])
{
maxxSon = size[v];
W_son[u] = v;
}
}
}
void dfs2(int x, int topf)
{
top[x] = topf;
id[x] = ++num;
if(!W_son[x]) return;
dfs2(W_son[x], topf);
for(int i=head[x]; i!=-1; i=edge[i].nex)
{
int y = edge[i].to;
if(y==W_son[x] || y==root[x]) continue;
dfs2(y, y);
}
}
void buildTree(int rt, int l, int r)
{
lazy[rt] = 0; mult[rt] = 1;
if(l == r)
{
tree[rt] = 0;
return;
}
int mid = (l + r)>>1;
buildTree(rt<<1, l, mid);
buildTree(rt<<1|1, mid+1, r);
tree[rt] = 0;
}
void pushup(int rt)
{
tree[rt] = tree[rt<<1] + tree[rt<<1|1];
}
void pushdown(int rt, int l, int r)
{
if(mult[rt]!=1)
{
mult[rt<<1]*=mult[rt]; lazy[rt<<1]*=mult[rt];
mult[rt<<1|1]*=mult[rt]; lazy[rt<<1|1]*=mult[rt];
tree[rt<<1]*=mult[rt];
tree[rt<<1|1]*=mult[rt];
mult[rt] = 1;
}
if(lazy[rt])
{
lazy[rt<<1] += lazy[rt];
lazy[rt<<1|1] += lazy[rt];
int mid = (l + r)>>1;
tree[rt<<1] += lazy[rt]*(mid - l + 1);
tree[rt<<1|1] += lazy[rt]*(r - mid);
lazy[rt] = 0;
}
}
void update_add(int rt, int l, int r, int ql, int qr, ull val)
{
if(ql<=l && qr>=r)
{
lazy[rt] += val;
tree[rt] += val*(r - l + 1);
return;
}
int mid = (l + r)>>1;
pushdown(rt, l, r);
if(ql>mid) update_add(rt<<1|1, mid+1, r, ql, qr, val);
else if(qr<=mid) update_add(rt<<1, l, mid, ql, qr, val);
else
{
update_add(rt<<1, l, mid, ql, qr, val);
update_add(rt<<1|1, mid+1, r, ql, qr, val);
}
pushup(rt);
}
void update_multi(int rt, int l, int r, int ql, int qr, ull val)
{
if(ql<=l && qr>=r)
{
lazy[rt] *= val;
mult[rt] *= val;
tree[rt] *= val;
return;
}
pushdown(rt, l, r);
int mid = (l + r)>>1;
if(ql>mid) update_multi(rt<<1|1, mid+1, r, ql, qr, val);
else if(qr<=mid) update_multi(rt<<1, l, mid, ql, qr, val);
else
{
update_multi(rt<<1, l, mid, ql, qr, val);
update_multi(rt<<1|1, mid+1, r, ql, qr, val);
}
pushup(rt);
}
void update_Range_add(int x, int y, ull val)
{
while(top[x] != top[y])
{
if(depth[top[x]] < depth[top[y]]) swap(x, y);
update_add(1, 1, N, id[top[x]], id[x], val);
x = root[top[x]];
}
if(depth[x] > depth[y]) swap(x, y);
update_add(1, 1, N, id[x], id[y], val);
}
void update_Range_Multi(int x, int y, ull val)
{
while(top[x] != top[y])
{
if(depth[top[x]] < depth[top[y]]) swap(x, y);
update_multi(1, 1, N, id[top[x]], id[x], val);
x = root[top[x]];
}
if(depth[x] > depth[y]) swap(x, y);
update_multi(1, 1, N, id[x], id[y], val);
}
ull query(int rt, int l, int r, int ql, int qr)
{
if(ql<=l && qr>=r) return tree[rt];
pushdown(rt, l, r);
int mid = (l + r)>>1;
if(ql>mid) return query(rt<<1|1, mid+1, r, ql, qr);
else if(qr<=mid) return query(rt<<1, l, mid, ql, qr);
else
{
ull ans = query(rt<<1, l, mid, ql, qr);
ans += query(rt<<1|1, mid+1, r, ql, qr);
return ans;
}
}
ull query_Range(int x, int y)
{
ull ans = 0;
while(top[x] != top[y])
{
if(depth[top[x]] < depth[top[y]]) swap(x, y);
ans += query(1, 1, N, id[top[x]], id[x]);
x = root[top[x]];
}
if(depth[x] > depth[y]) swap(x, y);
ans += query(1, 1, N, id[x], id[y]);
return ans;
}
void init()
{
cnt = num = 0;
memset(head, -1, sizeof(head));
memset(W_son, 0, sizeof(W_son));
}
int main()
{
while(scanf("%d", &N)!=EOF)
{
init();
for(int i=2; i<=N; i++)
{
int e1; scanf("%d", &e1);
addEddge(i, e1);
addEddge(e1, i);
}
dfs1(1, 1, 0);
dfs2(1, 1);
buildTree(1, 1, N);
scanf("%d", &Q);
while(Q--)
{
int op, u, v;
ull x;
scanf("%d", &op);
if(op == 1)
{
scanf("%d%d%llu", &u, &v, &x);
update_Range_Multi(u, v, x);
}
else if(op == 2)
{
scanf("%d%d%llu", &u, &v, &x);
update_Range_add(u, v, x);
}
else if(op == 3)
{
scanf("%d%d", &u, &v);
update_Range_Multi(u, v, -1);
update_Range_add(u, v, INF);
}
else
{
scanf("%d%d", &u, &v);
printf("%llu\n", query_Range(u, v));
}
}
}
return 0;
}

x修改来自模板:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;

const int N = 4e5+5;
int n, q, r, MOD;
int w[N], head[N], cnt;
int num;
int root[N];//保存结点 u 的父亲节点
int depth[N]; //保存结点 u 的深度值
int W_son[N];//保存重儿子
int size[N]; //保存以 u 为根的子树节点个数
int top[N];//保存当前节点所在链的顶端节点
int id[N];//保存树中每个节点剖分以后的新编号( DFS 的执行顺序)
int new_W[N]; //保存当前 dfs 标号在树中所对应的节点

struct Eddge
{
int nex, to;
Eddge(int a=-1, int b=0):nex(a), to(b) {}
} edge[N];
void addEddge(int u, int v)
{

edge[cnt] = Eddge(head[u], v);
head[u] = cnt++;
}
void dfs1(int u, int fa, int deep)
{

depth[u] = deep;
root[u] = fa;
size[u] = 1;
int maxSon = -1;
for(int i=head[u]; i!=-1; i=edge[i].nex)
{
int v = edge[i].to;
if(v == fa)
continue;
dfs1(v, u, deep+1);
size[u] += size[v];
if(size[v] > maxSon)
{
maxSon = size[v];
W_son[u] = v;
}
}
}
void dfs2(int u, int topf)
{

id[u] = ++num;
new_W[num] = w[u];
top[u] = topf;
if(!W_son[u])
return;
dfs2(W_son[u], topf);
for(int i=head[u]; i!=-1; i=edge[i].nex)
{
int v = edge[i].to;
if(v == W_son[u] || v == root[u])
continue;
dfs2(v, v);
}
}

struct Node
{
int l;
int r;
int add;
//ll mul;//区间乘法标记
//ll rep;//区间修改标记
int sum;//存1次方,2次方和,3次方和,如果超时注意删除无用的
} tree[N<<2];

int sum;
void pushdown(int k)
{
/* if(tree[k].rep)
{
tree[k<<1].rep = tree[k<<1|1].rep = tree[k].rep;
tree[k<<1].mul = tree[k<<1|1].mul = 0;
tree[k<<1].add = tree[k<<1|1].add = tree[k].rep;
tree[k<<1].sum = tree[k].rep % MOD * (tree[k<<1].r - tree[k<<1].l + 1) % MOD;
tree[k<<1|1].sum = tree[k].rep % MOD * (tree[k<<1|1].r - tree[k<<1|1].l + 1) % MOD;

tree[k].rep = 0;
}
if(tree[k].mul != 1)
{
tree[k<<1].add = tree[k<<1].add * tree[k].mul % MOD;
tree[k<<1|1].add = tree[k<<1|1].add * tree[k].mul % MOD;
tree[k<<1].mul = tree[k<<1].mul * tree[k].mul % MOD;
tree[k<<1|1].mul = tree[k<<1|1].mul * tree[k].mul % MOD;
tree[k<<1].sum = tree[k<<1].sum * tree[k].mul % MOD;
tree[k<<1|1].sum = tree[k<<1|1].sum * tree[k].mul % MOD;

tree[k].mul = 1;
} */
if(tree[k].add)
{
tree[k<<1].add = (tree[k<<1].add + tree[k].add) % MOD;
tree[k<<1|1].add = (tree[k<<1|1].add + tree[k].add) % MOD;
tree[k<<1].sum = (tree[k<<1].sum + tree[k].add * (tree[k<<1].r - tree[k<<1].l + 1) % MOD) % MOD;
tree[k<<1|1].sum = (tree[k<<1|1].sum + tree[k].add * (tree[k<<1|1].r - tree[k<<1|1].l + 1) % MOD) % MOD;

tree[k].add = 0;
}
}
void pushup(int k)
{
tree[k].sum = (tree[k<<1].sum + tree[k<<1|1].sum) % MOD;
}

void build(int k, int l, int r)
{
tree[k].l = l;
tree[k].r = r;
tree[k].add = 0;
//tree[k].mul = 1;
//tree[k].rep = 0;

if(l == r)
{
tree[k].sum = new_W[l];
return;
}
pushdown(k);
int mid = (l + r) >>1;
build(k<<1, l, mid);
build(k<<1|1, mid + 1, r);
pushup(k);
}
//dir=1,区间+;dir=2,区间乘;dir=3,区间修改
void interver(int k, int l, int r, int c, int dir)
{
if(tree[k].l >= l && tree[k].r <= r)
{
if(dir == 1)
{
tree[k].add = (tree[k].add + c) % MOD;
tree[k].sum = (tree[k].sum + c * (tree[k].r - tree[k].l + 1) % MOD) % MOD;
return;
}
/*else if(dir == 2)
{
tree[k].add = tree[k].add * c % MOD;
tree[k].mul = tree[k].mul * c % MOD;
tree[k].sum = tree[k].sum * c % MOD;
return;
}
else if(dir == 3)
{
tree[k].add = 0;
tree[k].mul = 1;
tree[k].rep = c;
tree[k].sum = c * (tree[k].r - tree[k].l + 1) % MOD;
return;
} */
}
pushdown(k);
int mid = (tree[k].l + tree[k].r) >>1;
if(l <= mid)
interver(k<<1, l,r, c, dir);
if(mid < r)
interver(k<<1|1,l,r, c, dir);
pushup(k);
}
//sum求和,求表示sum=a[l]^c+a[l+1]^c......+a[r]^c
void query(int k, int l, int r, int c)
{
if(tree[k].l >= l && tree[k].r <= r)
{
sum = (sum + tree[k].sum) % MOD;
return;
}
pushdown(k);
int mid = (tree[k].l + tree[k].r) >>1;
if(l <= mid)
query(k<<1, l,r, c);
if(mid < r)
query(k<<1|1, l,r, c);
pushup(k);
}
void update_range(int x, int y, int val)
{
while(top[x] != top[y])
{
if(depth[top[x]] < depth[top[y]]) swap(x, y);
interver(1, id[top[x]], id[x], val,1);
x = root[top[x]];
}
if(depth[x] > depth[y]) swap(x, y);
interver(1, id[x], id[y], val,1);
}

int Query_range(int x, int y)
{

int ans = 0;
while(top[x] != top[y])
{
if(depth[top[x]] < depth[top[y]])
swap(x, y);
sum=0;
query(1,id[top[x]], id[x],1);
ans = (ans + sum)%MOD;
x = root[top[x]];
}
if(depth[x] > depth[y])
swap(x, y);
sum=0;
query(1, id[x], id[y],1);
ans = (ans + sum)%MOD;
return ans;
}

void update_son(int x, int val)
{
interver(1, id[x], id[x]+size[x]-1, val,1);
}
int Query_son(int x)
{
sum=0;
query(1, id[x], id[x]+size[x]-1,1);
return sum;
}
void init()
{
cnt = num = 0;
memset(head, -1, sizeof(head));
memset(W_son, 0, sizeof(W_son));
}
int main()
{
while(scanf("%d%d%d%d", &n, &q, &r, &MOD)!=EOF)
{
init();
for(int i=1; i<=n; i++)
scanf("%d", &w[i]);
for(int i=1; i<n; i++)
{
int e1, e2;
scanf("%d%d", &e1, &e2);
addEddge(e1, e2);
addEddge(e2, e1);
}

dfs1(r, r, 0);
dfs2(r, r);

build(1, 1, n);
while(q--)
{
int op, x, y, z;
scanf("%d", &op);
if(op == 1)
{
scanf("%d%d%d", &x, &y, &z);
update_range(x, y, z);
}
else if(op == 2)
{
scanf("%d%d", &x, &y);
printf("%d\n", Query_range(x, y));
}
else if(op == 3)
{
scanf("%d%d", &x, &z);
update_son(x, z);
}
else
{

scanf("%d", &x);
printf("%d\n", Query_son(x));
}
}
}
return 0;
}