已知线段树最基本的操作是对于数组的单点修改和区间查询,因此有了以下推广:
之一:对一棵树进行单点修改和子树查询(不论这棵树是否为二叉树,不论节点是否前序遍历编号):
时间复杂度O(logn)即线段树的操作时间,退化成链也一样
原因,线段树查询需要知道l 和r,当节点前序遍历编号时, l就是该节点的编号, 所以我们只需知道r即可完成查询操作。将整棵树进行一遍dfs, 就有r = l + size[l] - 1,其中size[l]为以l为根节点的子树大小(包括l)
而当节点不是前序遍历编号时, 另开两个数组idx[], 和seg_idx[], 即可得到前序遍历编号。idx代表节点u对应的前序遍历编号,seg_idx代表顺序编号下第i个节点对应的原来的树的节点(反对应)
void dfs(int u) {
siz[u] = 1, idx[u] = ++cnt, seg_idx[cnt] = u;
for (int v : vec[u]) {
dfs(v);
siz[u] += siz[v];
}
}
ll query(int l, int r, int pos) {
ll ans = 1ll;
if (l <= nodes[pos].l && r >= nodes[pos].r) {
//附上操作
return ans;
}
int mid = nodes[pos].l + nodes[pos].r >> 1;
if (l <= mid)//操作1
if (r > mid)//操作2
return ans;
}
int main(){
ll ans = query(idx[root], idx[root] + siz[root] - 1, 1);
}
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lson pos << 1
#define rson pos << 1 | 1
#define pb push_back
const int mod = 1000000007;
const int N = 1e5 + 10;
struct Seg {
int l, r;
ll sum, fac[6];
}nodes[N << 2];
int n;
vector<int> vec[N];
int val[N];
int siz[N], idx[N],seg_idx[N], cnt = 0;
void dfs(int u) {
siz[u] = 1, idx[u] = ++cnt, seg_idx[cnt] = u;
for (int v : vec[u]) {
dfs(v);
siz[u] += siz[v];
}
}
int base[6] = { 2, 3, 5, 7, 11, 13 };
void get_factor(int x ,ll p[]) {
for (int i = 0; i < 6; i++) {
while (x % base[i] == 0) {
x /= base[i];
p[i]++;
}
}
}
void update(int pos) {
nodes[pos].sum = nodes[lson].sum * nodes[rson].sum % mod;
for (int i = 0; i < 6; i++)
nodes[pos].fac[i] = (nodes[lson].fac[i] + nodes[rson].fac[i]) % mod;
}
void build(int l, int r, int pos) {
nodes[pos] = { l, r };
if (l == r) {
nodes[pos].l = l;
nodes[pos].r = r;
nodes[pos].sum = val[seg_idx[l]];
get_factor(nodes[pos].sum, nodes[pos].fac);
return;
}
else {
int mid = l + r >> 1;
build(l, mid, lson);
build(mid + 1, r, rson);
update(pos);
}
}
void modify(int l, int r,int pos, int u, int x) {
if (l == r) {
nodes[pos].sum = nodes[pos].sum * x % mod;
ll temp[6] = { 0 };
get_factor(x, temp);
for (int i = 0; i < 6; i++) {
nodes[pos].fac[i] = (nodes[pos].fac[i] + temp[i]) % mod;
}
return;
}
int mid = l + r >> 1;
if (u <= mid) modify(l, mid,lson, u, x);
else modify(mid + 1, r,rson, u, x);
update(pos);
}
ll ans_array[6];
ll query(int l, int r, int pos) {
ll ans = 1ll;
if (l <= nodes[pos].l && r >= nodes[pos].r) {
for (int i = 0; i < 6; i++) {
ans_array[i] = (ans_array[i] + nodes[pos].fac[i]) % mod;
}
ans = ans * nodes[pos].sum % mod;
return ans;
}
int mid = nodes[pos].l + nodes[pos].r >> 1;
if (l <= mid)ans = ans * query(l, r, lson) % mod;
if (r > mid)ans = ans * query(l, r, rson) % mod;
return ans;
}
void solve() {
scanf("%d", &n);
int u, v;
for (int i = 0; i < n - 1; i++) scanf("%d%d", &u, &v), vec[u].pb(v);
for (int i = 0; i < n; i++) scanf("%d", &val[i]);
dfs(0);
build(1, cnt, 1);
int q;
scanf("%d", &q);
while (q--) {
char str[10];
scanf("%s", str);
if (str[0] == 'R') {
int root;
scanf("%d", &root);
for (int i = 0; i < 6; i++)ans_array[i] = 0;
ll ans = query(idx[root], idx[root] + siz[root] - 1, 1);
ll ans_f = 1;
for (int i = 0; i < 6; i++)ans_f = ans_f * (ans_array[i] + 1) % mod;
printf("%lld %lld\n", ans, ans_f);
}
else if (str[0] == 'S') {
int u, x;
scanf("%d%d", &u, &x);
modify(1, cnt,1, idx[u], x);
}
}
}
int main() {
int t = 1;
while (t--)
solve();
}