Luogu6018 [Ynoi2010]Fusion tree
Luogu6018 [Ynoi2010]Fusion tree
\(Trie\)树
\(Trie\)树的奇怪标记实在不是很了解,所以做一下这题。
在每个节点上建\(Trie\)树维护子节点信息,单独维护父节点信息。
如何维护异或和?我们可以维护\(Trie\)树上同一深度节点的奇偶性,即可查出每一位是否是\(1\)。
处理全局\(+1\)操作,我们考虑从低位到高位建\(Trie\)树,显然\(+1\)是使得第一个\(0\)变成\(1\),\(0\)以前的\(1\)变成\(0\)。
我们可以从根节点出发,交换\(0,1\)两棵子树,把\(0\)变成\(1\)就相当于加\(1\)。继续向\(0\)子树(也就是原来的\(1\)子树)递归,就可以完成进位操作,画图很容易明白。
还有单点修改,直接搜索\(Trie\)树即可。
复杂度\(O(n \log n)\)。
\(Code:\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 500005
using namespace std;
int n,m,x,y,opt;
int rt[N],f[N];
struct Trie
{
int tr[N*22][2],tot;
int fa[N*22],sz[N*22],on[N*22],dep[N][22];
int ans[N];
void push_up(int id,int x,int cs)
{
if (!x)
return;
if (on[x])
{
ans[id]-=dep[id][cs] << cs;
dep[id][cs]^=1;
ans[id]+=dep[id][cs] << cs;
}
if (cs!=20)
sz[x]=sz[tr[x][0]]+sz[tr[x][1]];
push_up(id,fa[x],cs-1);
}
void insert(int rt,int x)
{
int u=rt;
for (int i=0;i<=20;++i)
{
int son=(x >> i) & 1;
if (!tr[u][son])
tr[u][son]=++tot,fa[tot]=u,on[tot]=son;
u=tr[u][son];
}
++sz[u];
push_up(rt,u,20);
}
void erase(int rt,int x)
{
int u=rt;
for (int i=0;i<=20;++i)
{
int son=(x >> i) & 1;
u=tr[u][son];
}
--sz[u];
push_up(rt,u,20);
}
void push_add(int rt,int x,int cs)
{
if (!x)
return;
ans[rt]-=dep[rt][cs+1] << cs+1;
dep[rt][cs+1]^=(sz[tr[x][0]] & 1)^(sz[tr[x][1]] & 1);
ans[rt]+=dep[rt][cs+1] << cs+1;
swap(tr[x][0],tr[x][1]),on[tr[x][0]]=0,on[tr[x][1]]=1;
push_add(rt,tr[x][0],cs+1);
}
}T;
struct edge
{
int nxt,v;
edge (int Nxt=0,int V=0)
{
nxt=Nxt,v=V;
}
}e[N << 1];
int tot,fr[N],a[N];
int tag[N];
int getval(int x)
{
return a[x]+tag[f[x]];
}
void modify(int x,int y)
{
if (f[x])
T.erase(rt[f[x]],getval(x));
a[x]=y-tag[f[x]];
if (f[x])
T.insert(rt[f[x]],y);
}
void add(int x,int y)
{
++tot;
e[tot]=edge(fr[x],y),fr[x]=tot;
}
void dfs(int u,int F)
{
for (int i=fr[u];i;i=e[i].nxt)
{
int v=e[i].v;
if (v==F)
continue;
f[v]=u;
T.insert(rt[u],a[v]);
dfs(v,u);
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
for (int i=1;i<=n;++i)
scanf("%d",&a[i]);
for (int i=1;i<=n;++i)
rt[i]=++T.tot;
dfs(1,0);
for (int i=1;i<=m;++i)
{
scanf("%d",&opt);
if (opt==1)
{
scanf("%d",&x);
if (f[x])
modify(f[x],getval(f[x])+1);
T.push_add(x,rt[x],-1);
++tag[x];
} else
if (opt==2)
{
scanf("%d%d",&x,&y);
modify(x,getval(x)-y);
} else
{
scanf("%d",&x);
printf("%d\n",T.ans[x]^((!f[x])?0:getval(f[x])));
}
}
return 0;
}