Luogu P6623 [省選聯考 2020 A 卷] 樹
阿新 • • 發佈:2020-07-28
這套路和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; }