题意:求一棵树的所有权值异或起来为 的联通块个数,单点修改,
先考虑朴素的
表示 的子树,强制选 ,异或起来为 的方案数
直接先 全部变成点乘,最后再还原
然后还要求一个子树的前缀和,不妨令为
直接上链分治,定义 表示轻儿子和自己和起来的 值
于是有转移
写成矩阵乘法的形式
把中间 4 个关键点单独算就可以只有 4 倍小常数
关于全局平衡二叉树:
对每一条重链建一棵二叉树,然后一条重链的二叉树的根连向轻边的
直接建深度是 的
我们对重链建的时候不从中间剖,我们对除重儿子之外的 从中间分
这样做是 的
每次修改的时候暴力跳 ,然后 ,如果切轻链的就要重新算一下
有一个头疼的是重新算的时候有可能除以 0,所以要记录一下 0 的个数,将一个数表示成 的形式
#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int N = 3e4 + 5, M = 130;
cs int Mod = 1e4 + 7, inv2 = (Mod+1)>>1;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1; }
while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
return cnt * f;
}
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int ksm(int a, int b){ int ans = 1; for(;b;b>>=1,a=mul(a,a)) if(b&1) ans = mul(ans, a); return ans; }
void Add(int &a, int b){ a = add(a, b); }
void Mul(int &a, int b){ a = mul(a, b); }
void Dec(int &a, int b){ a = dec(a, b); }
int first[N], nxt[N<<1], to[N<<1], tot;
void adde(int x, int y){ nxt[++tot] = first[x], first[x] = tot, to[tot] = y; }
int inv[Mod];
int n, S, m, vl[N], fw[M][M];
int siz[N], son[N], ans[M];
void pre_dfs(int u, int f){
siz[u] = 1; for(int i=first[u];i;i=nxt[i]){
int t = to[i]; if(t == f) continue; pre_dfs(t, u);
siz[u] += siz[t]; if(siz[t] > siz[son[u]]) son[u] = t;
}
}
struct tag{
int x, y;
tag(int _x = 0, int _y = 0){ x = _x, y = _y; }
void operator = (int v){ v ? (x = v, y = 0) : (x = y = 1); }
void operator *= (int v){ v ? x = mul(x, v) : ++y; }
void operator /= (int v){ v ? x = mul(x, inv[v]) : --y; }
operator int (){ return y ? 0 : x; }
};
struct data{
int a[M], b[M], c[M], d[M];
void operator = (cs data &A){
memcpy(a, A.a, sizeof(int)*S);
memcpy(b, A.b, sizeof(int)*S);
memcpy(c, A.c, sizeof(int)*S);
memcpy(d, A.d, sizeof(int)*S);
}
};
void Inc(data &C, data A, data B){
for(int i = 0; i < S; i++){
C.a[i] = mul(A.a[i], B.a[i]);
C.b[i] = add(mul(A.a[i], B.b[i]), A.b[i]);
C.c[i] = add(mul(A.c[i], B.a[i]), B.c[i]);
C.d[i] = add(mul(A.c[i], B.b[i]), add(A.d[i], B.d[i]));
}
}
void FWT(int *a, int typ){
for(int i = 1; i < S; i <<= 1)
for(int j = 0; j < S; j += (i<<1))
for(int k = 0; k < i; k++){
int x = a[k + j], y = a[k + j + i];
a[k + j] = add(x, y); a[k + j + i] = dec(x, y);
if(typ == -1) Mul(a[k + j], inv2), Mul(a[k + j + i], inv2);
}
}
namespace GBT{
int rt, cn[N], tp;
int lsz[N], ch[N][2], fa[N];
data w[N], a[N];
tag F[N][M]; int G[N][M];
void init_node(int x){
int *W = fw[vl[x]]; data &A = w[x];
for(int i = 0; i < S; i++){
A.a[i] = mul(F[x][i], W[i]);
A.d[i] = add(A.a[i], G[x][i]);
}
memcpy(A.b, A.a, sizeof(int)*S);
memcpy(A.c, A.a, sizeof(int)*S);
}
void pushup(int x){
Inc(a[x], a[ch[x][0]], w[x]);
Inc(a[x], a[x], a[ch[x][1]]);
}
void ins(int u, int v){
int *t1 = a[v].c, *t2 = a[v].d;
for(int i = 0; i < S; i++){
F[u][i] *= add(t1[i], 1);
Add(G[u][i], t2[i]);
}
}
void del(int u, int v){
int *t1 = a[v].c, *t2 = a[v].d;
for(int i = 0; i < S; i++){
F[u][i] /= add(t1[i], 1);
Dec(G[u][i], t2[i]);
}
}
int subbuild(int l, int r){
if(l == r){ pushup(cn[l]); return cn[l]; } if(l > r) return 0;
int tot = 0; for(int i = l; i <= r; i++) tot += lsz[cn[i]];
for(int i = l, now = lsz[cn[l]]; i <= r; now += lsz[cn[++i]])
if(now * 2 >= tot){
ch[cn[i]][0] = subbuild(l, i-1);
ch[cn[i]][1] = subbuild(i+1, r);
fa[ch[cn[i]][0]] = fa[ch[cn[i]][1]] = cn[i]; pushup(cn[i]);
return cn[i];
}
}
int build(int u){
for(int p = u; p; p = son[p]) lsz[p] = siz[p] - siz[son[p]];
for(int p = u; p; p = son[p])
for(int e = first[p]; e; e = nxt[e]){
int t = to[e]; if(!lsz[t]){ t = build(t); fa[t] = p; ins(p, t); }
} tp = 0;
for(int p = u; p; p = son[p]) cn[++tp] = p, init_node(p);
reverse(cn + 1, cn + tp + 1);
return subbuild(1, tp);
}
bool hv;
void Get(){
if(hv) return; hv = true;
memcpy(ans, a[rt].d, sizeof(int)*S); FWT(ans, -1);
}
bool isroot(int x){ return ch[fa[x]][0] != x && ch[fa[x]][1] != x; }
void modify(){
hv = false;
int u = read(); vl[u] = read(); init_node(u);
while(u){
if(isroot(u) && fa[u]){
del(fa[u], u); pushup(u); ins(fa[u], u); init_node(fa[u]);
} else pushup(u); //cout << "modify "<<u << endl;debug(a[u].d);
u = fa[u];
}
}
void init(){
for(int i = 1; i <= n; i++)
for(int j = 0; j < S; j++) F[i][j] = 1;
for(int i = 0; i < S; i++) w[0].a[i] = a[0].a[i] = 1;
rt = build(1);
}
}
int main(){
inv[0] = inv[1] = 1;
for(int i = 2; i < Mod; i++) inv[i] = mul(Mod-Mod/i, inv[Mod%i]);
n = read(), S = read();
for(int i = 1; i <= n; i++) vl[i] = read();
for(int i = 1; i < n; i++){ int x = read(), y = read(); adde(x, y); adde(y, x); }
for(int i = 0; i < S; i++) fw[i][i] = 1, FWT(fw[i], 1);
pre_dfs(1, 0); GBT::init();
m = read();
while(m--){
char opt[10]; scanf("%s", opt);
if(opt[0] == 'Q'){ GBT::Get(); cout << ans[read()] << '\n'; }
if(opt[0] == 'C') GBT::modify();
} return 0;
}