「聯合省選 2020 A」樹
阿新 • • 發佈:2022-04-17
「聯合省選 2020 A」樹
按位考慮。
對於一個點來說,其兒子到其的距離是 \(dep_v-u\)。
那麼其兒子做出的貢獻是 \(V_v+dep_v-dep_u\)。
在模 \(2^{i+1}\) 的意義下若 \(2_i\le V_v+dep_v-dep_u< 2^{i+1}\) 則 \(v\) 會對 \(u\) 產生一個 \(2^i\) 的貢獻。
也就是說,我們求出以 \(u\) 為根的子樹中所有點的 \(V_v+dep_v\) 的桶並且對 \([2^i+dep_u.2^{i+1}+dep_u)\) 這個區間內做一個統計即可。
注意,這裡的區間都應該是在模 \(2^{i+1}\) 的意義下的,而我們上述式子在程式碼中應該轉換成模 \(2^{i+1}\)
求出以 \(u\) 為根的子樹中所有點權值的桶是一個經典問題,我們可以 dfs 一遍,然後將進入 \(u\) 和從 \(u\) 出去的桶做一個差分即可得到。
複雜度 \(O(n\log^2 V)\)。
程式碼如下:
#include<bits/stdc++.h> #define ll long long using namespace std; const int MAXN = (1<<21)+5; const int MX = (1<<21); bool Small; struct BIT { #define lowbit(i) (i&(-i)) int t[MAXN],mx; BIT(){memset(t,0,sizeof t);} void upd(int p,int x){for(int i=p;i<=mx;i+=lowbit(i))t[i]^=x;} ll que(int p){ll r=0;for(int i=p;i;i-=lowbit(i))r^=t[i];return r;} ll Q(int l,int r){return que(r)^que(l-1);} }t[21]; vector <int> e[MAXN]; int n; ll v[MAXN],val[MAXN],Ans; bool Sunny; void Calc(int p,int d) { for(int i=0;i<=20;++i) { int l=(1<<i)+d,r=(1<<(i+1))+d-1; l=(l&((1<<i+1)-1))+1;r=(r&((1<<i+1)-1))+1; if(r<l)val[p]^=t[i].Q(l,1<<(i+1))^t[i].Q(1,r); else val[p]^=t[i].Q(l,r); } } void dfs(int p,int d) { v[p]+=d; Calc(p,d); for(int i=0;i<=20;++i) t[i].upd((v[p]&((1<<i+1)-1))+1,(1<<i)); for(int v:e[p]) dfs(v,d+1); Calc(p,d); Ans+=val[p]; } int main() { scanf("%d",&n); for(int i=0;i<=20;++i) t[i].mx=(1<<i+1); for(int i=1;i<=n;++i) scanf("%d",&v[i]); for(int i=2;i<=n;++i) { int fa;scanf("%d",&fa); e[fa].push_back(i); } dfs(1,0); printf("%lld\n",Ans); return 0; }