Luogu P6623 [省选联考 2020 A 卷] 树
这套路和AGC044C几乎一样,做过那题的就跟做原题一样
显然考虑用0/1Trie维护答案,考虑从子树向这个点合并,显然我们的操作有:
加入一个数,Trie树合并,Trie树集体加\(1\),前两个非常直观,考虑最后一个操作
我们把Trie树反着建,从低位到高位建树,这样每次加\(1\)操作其实就是交换\(0,1\)儿子之后递归处理\(0\)儿子
统计出每个点\(0,1\)儿子的个数以及以它为根的Trie树中不同深度的\(0,1\)儿子个数之和,可以轻松维护答案
#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int P=21,N=1<<P;
struct edge
{
int to,nxt;
}e[N]; int n,head[N],v[N],x,cnt; long long ans;
inline void addedge(CI x,CI y)
{
e[++cnt]=(edge){y,head[x]}; head[x]=cnt;
}
class Trie
{
private:
struct segment
{
int ch[2],c[2];
}node[N*P]; int rt[N],cq[N][P][2],tot;
#define lc(x) node[x].ch[0]
#define rc(x) node[x].ch[1]
#define C(x,y) node[x].c[y]
inline void _insert(int& now,CI val,CI id,CI dep=0)
{
if (dep==P) return; if (!now) now=++tot;
if ((val>>dep)&1) _insert(rc(now),val,id,dep+1),++C(now,1),++cq[id][dep][1];
else _insert(lc(now),val,id,dep+1),++C(now,0),++cq[id][dep][0];
}
inline void _add(CI now,CI id,CI dep=0)
{
if (!now||dep==P) return; RI i; for (i=0;i<2;++i) cq[id][dep][i]-=C(now,i);
swap(lc(now),rc(now)); swap(C(now,0),C(now,1));
for (i=0;i<2;++i) cq[id][dep][i]+=C(now,i); _add(lc(now),id,dep+1);
}
inline int _merge(CI x,CI y,CI dep=0)
{
if (!x||!y||dep==P) return x|y; for (RI i=0;i<2;++i) C(x,i)+=C(y,i);
lc(x)=_merge(lc(x),lc(y),dep+1); rc(x)=_merge(rc(x),rc(y),dep+1); return x;
}
public:
inline void insert(CI pos,CI mv)
{
_insert(rt[pos],mv,pos);
}
inline void add(CI pos)
{
_add(rt[pos],pos);
}
inline void merge(CI x,CI y)
{
rt[x]=_merge(rt[x],rt[y]); for (RI i=0,j;i<P;++i)
for (j=0;j<2;++j) cq[x][i][j]+=cq[y][i][j];
}
inline int query(CI pos,int ret=0)
{
for (RI i=0;i<P;++i) if (cq[pos][i][1]&1) ret|=(1<<i); return ret;
}
#undef lc
#undef rc
#undef V
}T;
#define to e[i].to
inline void DFS(CI now=1)
{
T.insert(now,v[now]); for (RI i=head[now];i;i=e[i].nxt)
DFS(to),T.add(to),T.merge(now,to); ans+=T.query(now);
}
#undef to
int main()
{
RI i; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&v[i]);
for (i=2;i<=n;++i) scanf("%d",&x),addedge(x,i);
return DFS(),printf("%lld",ans),0;
}
辣鸡老年选手AFO在即