*题解:P6018 [Ynoi2010] Fusion tree
解析
对父亲单独处理,问题变为序列整体加 \(1\),序列单点加,求异或和。直接建 Trie 难以维护整体加 \(1\),但事实上我们可以对每个结点倒着建一个从低位往高位走的 Trie,这样加 \(1\) 就变成了交换连向两棵子树的边权并向交换前边权为 \(1\) 的那条边走,递归重复此过程。
实现上,在 Trie 上维护一个子树异或和和子树大小,push_up 时,若边权为 \(1\) 的那条边连接的子树的大小为奇数,则异或和的该位为 \(1\),否则为 \(0\)。除此之外,由于我们单独处理了父亲,而整体加 \(1\) 会影响操作点 \(x\) 的所有儿子的儿子的父亲,所以需要在 \(x\) 处记录该位置上进行了多少次操作 \(1\),对于父亲单点加,对父亲的父亲的 Trie 进行修改即可。
时间复杂度 \(O((n + m)\log a)\)。
代码
#include<bits/stdc++.h>
#define ls(x) ((x) << 1)
#define rs(x) (((x) << 1) | 1)
#define mid ((l + r) >> 1)
#define getchar() getchar_unlocked()
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef pair<int,int> pii;
const int N = 5e5 + 5,M = 19;
int rt[N],son[N * M][2],sum[N * M],siz[N * M],cnt;
int ocnt[N],val[N];
vector<int> t[N];
int fa[N];
void push_up(int x,int k){
siz[x] = siz[son[x][0]] + siz[son[x][1]];
sum[x] = (siz[son[x][1]] % 2 == 0 ? 0 : (1 << k)) | (sum[son[x][0]] ^ sum[son[x][1]]);
}
void insert(int &x,int val,int k){
if(!x) x = ++cnt;
if(k == M - 1){
siz[x]++;
return;
}
insert(son[x][bool(val & (1 << k))],val,k + 1);
push_up(x,k);
}
void erase(int &x,int val,int k){
if(k == M - 1){
siz[x]--;
return;
}
erase(son[x][bool(val & (1 << k))],val,k + 1);
push_up(x,k);
}
void add1(int &x,int k){
if(!x) return;
swap(son[x][0],son[x][1]);
add1(son[x][0],k + 1);
push_up(x,k);
}
void dfs(int x,int f){
fa[x] = f;
for(int nx : t[x])if(nx != f){
dfs(nx,x);
insert(rt[x],val[nx],0);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
// freopen("in.txt","r",stdin);
// freopen("out1.txt","w",stdout);
int n,m;
cin>>n>>m;
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
t[u].push_back(v);
t[v].push_back(u);
}
for(int i=1;i<=n;i++){
cin>>val[i];
}
dfs(1,0);
while(m--){
int op,x,v;
cin>>op>>x;
if(op == 1){
add1(rt[x],0);
ocnt[x]++;
if(fa[x]){
int ff = fa[fa[x]];
if(ff){
erase(rt[ff],val[fa[x]] + ocnt[ff],0);
}
val[fa[x]]++;
if(ff){
insert(rt[ff],val[fa[x]] + ocnt[ff],0);
}
}
}else if(op == 2){
cin>>v;
if(fa[x]){
erase(rt[fa[x]],val[x] + ocnt[fa[x]],0);
}
val[x] -= v;
if(fa[x]){
insert(rt[fa[x]],val[x] + ocnt[fa[x]],0);
}
}else{
int res = sum[rt[x]];
int k = 0;
if(fa[x]){
k += val[fa[x]];
if(fa[fa[x]]){
k += ocnt[fa[fa[x]]];
}
}
res ^= k;
cout<<res<<'\n';
}
}
return 0;
}

浙公网安备 33010602011771号